package org.reenscape.model;
import org.reenscape.lib.*;
import org.reenscape.updater.*;
import org.reenscape.skill.*;
import org.reenscape.model.*;
import org.reenscape.auth.LoginAuth;
import org.reenscape.*;
import java.io.*;
import java.util.StringTokenizer;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class PacketParser extends Player implements Runnable {

	public void println_debug(String str) {
		Library.print.println("[client-"+playerId+"-"+playerName+"]: "+str);
	}
	public void println(String str) {
		Library.print.println("[client-"+playerId+"-"+playerName+"]: "+str);
	}
	
	public void setAnimation(int i) {
		pEmote = i;
		updateRequired = true;
		appearanceUpdateRequired = true;
	}
	public void resetAnimation() {
		pEmote = playerSE;
		updateRequired = true;
		appearanceUpdateRequired = true;
	}
	
	public void randomize(int o,int oo,int ooo,int oooo) {
		outStream.createFrame(53);
		outStream.writeWord(o);
		outStream.writeWord(oo);
		outStream.writeByte(ooo);
		outStream.writeWordBigEndianA(oooo);
		flushOutStream();
	}
	
	public void sendFrame126(String s, int id) {
		outStream.createFrameVarSizeWord(126);
		outStream.writeString(s);
		outStream.writeWordA(id);
		outStream.endFrameVarSizeWord();
		flushOutStream();
	}

	public void sendFrame248(int MainFrame, int SubFrame) {
		outStream.createFrame(248);
		outStream.writeWordA(MainFrame);
		outStream.writeWord(SubFrame);
		flushOutStream();
	}

	public void sendFrame200(int MainFrame, int SubFrame) {
		outStream.createFrame(200);
		outStream.writeWord(MainFrame);
		outStream.writeWord(SubFrame);
		flushOutStream();
	}

	public void sendFrame75(int MainFrame, int SubFrame) {
		outStream.createFrame(75);
		outStream.writeWordBigEndianA(MainFrame);
		outStream.writeWordBigEndianA(SubFrame);
		flushOutStream();
	}

	public void sendFrame164(int Frame) {
		outStream.createFrame(164);
		outStream.writeWordBigEndian_dup(Frame);
		flushOutStream();
	}

	public void sendFrame246(int MainFrame, int SubFrame, int SubFrame2) {
		outStream.createFrame(246);
		outStream.writeWordBigEndian(MainFrame);
		outStream.writeWord(SubFrame);
		outStream.writeWord(SubFrame2);
		flushOutStream();
	}

	public void sendFrame185(int Frame) {
		outStream.createFrame(185);
		outStream.writeWordBigEndianA(Frame);
		flushOutStream();
	}
	
	public void sendFrame171(int MainFrame, int SubFrame) {
		outStream.createFrame(171);
		outStream.writeByte(MainFrame);
		outStream.writeWord(SubFrame);
		flushOutStream();
	}

	public void sendFrame208(int Frame) {
		outStream.createFrame(208);
		outStream.writeWordBigEndian_dup(Frame);
	}


	public void RemoveAllWindows() {
		outStream.createFrame(219);
		flushOutStream();
	}

	public void sendQuestSomething(int id) {
		outStream.createFrame(79);
		outStream.writeWordBigEndian(id);
		outStream.writeWordA(0);
		flushOutStream();
	}

	public void clearQuestInterface() {
		for(int x = 0; x < QuestInterface.length; x++) {
			sendFrame126("", QuestInterface[x]);
		}
	}
	public void showInterface(int interfaceid) {
		outStream.createFrame(97);
		outStream.writeWord(interfaceid);
		flushOutStream();
	}
	
	public int[] QuestInterface = {
		8145, 8147, 8148, 8149, 8150, 8151, 8152, 8153, 8154, 8155, 8156, 8157, 8158, 8159, 8160, 8161, 8162, 
		8163, 8164, 8165, 8166, 8167, 8168, 8169, 8170, 8171, 8172, 8173, 8174, 8175, 8176, 8177, 8178, 8179,
		8180, 8181, 8182, 8183, 8184, 8185, 8186, 8187, 8188, 8189, 8190, 8191, 8192, 8193, 8194, 8195, 12174,
		12175, 12176, 12177, 12178, 12179, 12180, 12181, 12182, 12183, 12184, 12185, 12186, 12187, 12188, 12189, 
		12190, 12191, 12192, 12193, 12194, 12195, 12196, 12197, 12198, 12199, 12200, 12201, 12202, 12203, 12204, 
		12205, 12206, 12207, 12208, 12209, 12210, 12211, 12212, 12213, 12214, 12215, 12216, 12217, 12218, 12219, 
		12220, 12221, 12222, 12223
	};
		
	public String statName[] = {"attack", "defence", "strength", "hitpoints", "ranged", "prayer", "magic", "cooking",
		"woodcutting", "fletching", "fishing", "firemaking", "crafting", "smithing", "mining", "herblore", "agility",
		 "thieving", "slayer", "farming", "runecrafting"
    	};
	public String BonusName[] = {"Stab", "Slash", "Crush", "Magic", "Range", "Stab", "Slash", "Crush", "Magic", "Range", 
		"Strength", "Prayer"
	};
	public int pCHead;
	public int pCBeard;
	public int pCTorso;
	public int pCArms;
	public int pCHands;
	public int pCLegs;
	public int pCFeet;
	public int pColor;
	public int pGender;
	public int i;
	public int gender;

	public int XremoveSlot = 0;
	public int XinterfaceID = 0;
	public int XremoveID = 0;
	private long lastPickup = 0;
	private int emotes = 0;

	public int stairs = 0;
	public int stairDistance = 1;
	public int stairDistanceAdd = 0;
	public int doors = -1;
	public int bow = -1;

	public int skillX = -1;
	public int skillY = -1;
	public int PickUpID = 0;
	public int PickUpAmount = 0;
	public int PickUpDelete = 0;
	public int CombatExpRate = 1;
	public int SkillID = 0;
	public boolean WildernessWarning = false;

	public int WanneBank = 0;
	public int WanneShop = 0;
	
	public int LogoutTimer = 0;
	public int StunnedTimer = 0;

	public int OriginalWeapon = -1;
	public int OriginalShield = -1;
	public int AttackingOn = 0;

	public static final int bufferSize = 100000;
	private java.net.Socket mySock;
	private java.io.InputStream in;
	private java.io.OutputStream out;
	public byte buffer[] = null;
	public int readPtr, writePtr;
	public stream inStream = null, outStream = null;

	public Cryption inStreamDecryption = null, outStreamDecryption = null;


	public int lowMemoryVersion = 0;

	public int timeOutCounter = 0;		// to detect timeouts on the connection to the client

	public int returnCode = 2; //Tells the client if the login was successfull

	public PacketParser(java.net.Socket s, int _playerId) {
		super(_playerId);
		mySock = s;
		try {
			in = s.getInputStream();
			out = s.getOutputStream();
		} catch(java.io.IOException ioe) {
			Print.error("Unable to create output and input streams.","PacketParser","Constructor", ioe);
		}

		outStream = new stream(new byte[bufferSize]);
		outStream.currentOffset = 0;
		inStream = new stream(new byte[bufferSize]);
		inStream.currentOffset = 0;

		readPtr = writePtr = 0;
		buffer = buffer = new byte[bufferSize];
	}

	public void shutdownError(String errorMessage) {
		Library.print.println("Fatal: "+errorMessage);
		destruct();
	}
	
	public int fishing[] = {0,0,0,0,};
	public int smithing[] = {0,0,0,0,0,};
	public int smelting[] = {0,0,0,0,};
	
	
  public int GetBlockAnim(int id) {
    if(id == 4755) { return 2063; } // veracs flail
    if(id == 4153) { return 1666; } // maul
    else { return 1834; }
  }
  
  public int getItemSlotReturn(int itemID) {
    for(int slot=0; slot < playerItems.length; slot++) {
      if(playerItems[slot] ==(itemID +1)) {
        return slot;
      }
    }
    return -1;
  }
  
  public int amountOfItem(int itemID) {
    int i1 = 0;
    for(int i = 0; i < 28; i++) {
      if(playerItems[i] ==(itemID +1)) {
        i1++;
      }
    }
    return i1;
  }
  
  public boolean playerHasItem(int itemID) {
    for(int i=0; i<playerItems.length; i++) {
      if(playerItems[i] == itemID) {
        return true;
      }
    }
    return false;
  }
	
	public void destruct() {
		if(mySock == null) return;		// already shutdown
		try {
			ClientUpdater.players[playerId] = null;
			if(playerName != null) Library.print.println(playerName+" has disconnected from the server.");
			disconnected = true;

			if(in != null) in.close();
			if(out != null) out.close();
			mySock.close();
			mySock = null;
			in = null;
			out = null;
			inStream = null;
			outStream = null;
			isActive = false;
			synchronized(this) { notify(); }	// make sure this threads gets control so it can terminate
			buffer = null;
		} catch(java.io.IOException ioe) {
			ioe.printStackTrace();
		}
		super.destruct();
	}





	// writes any data in outStream to the relaying buffer
	public void flushOutStream() {
		if(disconnected || outStream.currentOffset == 0) return;

		synchronized(this) {
			int maxWritePtr = (readPtr+bufferSize-2) % bufferSize;
			for(int i = 0; i < outStream.currentOffset; i++) {
				buffer[writePtr] = outStream.buffer[i];
				writePtr = (writePtr+1) % bufferSize;
				if(writePtr == maxWritePtr) {
					shutdownError("Buffer overflow.");
					disconnected = true;
					return;
				}
          		}
			outStream.currentOffset = 0;

			notify();
		}
   	 }

	// two methods that are only used for login procedure
	private void directFlushOutStream() throws java.io.IOException {
		out.write(outStream.buffer, 0, outStream.currentOffset);
		outStream.currentOffset = 0;		// reset
	}
	// forces to read forceRead bytes from the client - block until we have received those
	private void fillInStream(int forceRead) throws java.io.IOException {
		inStream.currentOffset = 0;
		in.read(inStream.buffer, 0, forceRead);
	}

	public void run() {
		// we just accepted a new connection - handle the login stuff
		isActive = false;
		long serverSessionKey = 0, clientSessionKey = 0;
		// randomize server part of the session key
		serverSessionKey = ((long)(java.lang.Math.random() * 99999999D) << 32) + (long)(java.lang.Math.random() * 99999999D);

		try {
			fillInStream(2);
			if(inStream.readUnsignedByte() != 14) {
				shutdownError("[BL]Expected login Id 14 from client.");
				Server.blacklist(connectedFrom);
				return;
			}
			// this is part of the usename. Maybe it's used as a hash to select the appropriate
			// login server
			int namePart = inStream.readUnsignedByte();
			for(int i = 0; i < 8; i++) out.write(0);		// is being ignored by the client

			// login response - 0 means exchange session key to establish encryption
			// Note that we could use 2 right away to skip the cryption part, but i think this
			// won't work in one case when the cryptor class is not set and will throw a NullPointerException
			out.write(0);

			// send the server part of the session Id used (client+server part together are used as cryption key)
			outStream.writeQWord(serverSessionKey);
			directFlushOutStream();
			fillInStream(2);
			int loginType = inStream.readUnsignedByte();	// this is either 16 (new login) or 18 (reconnect after lost connection)
			if(loginType != 16 && loginType != 18) {
				shutdownError("[BL]Unexpected login type "+loginType);
				Server.blacklist(connectedFrom);
				return;
			}
			int loginPacketSize = inStream.readUnsignedByte();
			int loginEncryptPacketSize = loginPacketSize-(36+1+1+2);	// the size of the RSA encrypted part (containing password)
			if(loginEncryptPacketSize <= 0) {
				shutdownError("Zero RSA packet size!");
				return;
			}
			fillInStream(loginPacketSize);
			if(inStream.readUnsignedByte() != 255 || inStream.readUnsignedWord() != 317) {
				shutdownError("[BL]Not using correct client");
				Server.blacklist(connectedFrom);
				return;
			}
			lowMemoryVersion = inStream.readUnsignedByte();
			for(int i = 0; i < 9; i++) {
				String junk = Integer.toHexString(inStream.readDWord());
			}

			loginEncryptPacketSize--;		// don't count length byte
			int tmp = inStream.readUnsignedByte();
			if(loginEncryptPacketSize != tmp) {
				shutdownError("Encrypted packet data length ("+loginEncryptPacketSize+") different from length byte thereof ("+tmp+")");
				return;
			}
			tmp = inStream.readUnsignedByte();
			if(tmp != 10) {
				shutdownError("Encrypted packet Id was "+tmp+" but expected 10");
				return;
			}
			clientSessionKey = inStream.readQWord();
			serverSessionKey = inStream.readQWord();

			int UID = inStream.readDWord(); //Client UID

			playerName = inStream.readString();
			if(playerName == null || playerName.length() == 0) playerName = "player"+playerId;
			playerPass = inStream.readString();

			playerServer = "localhost";

			int sessionKey[] = new int[4];
			sessionKey[0] = (int)(clientSessionKey >> 32);
			sessionKey[1] = (int)clientSessionKey;
			sessionKey[2] = (int)(serverSessionKey >> 32);
			sessionKey[3] = (int)serverSessionKey;

			inStreamDecryption = new Cryption(sessionKey);
			for(int i = 0; i < 4; i++) sessionKey[i] += 50;

			outStreamDecryption = new Cryption(sessionKey);
			outStream.packetEncryption = outStreamDecryption;

			returnCode = LoginAuth.Check(this, playerName, connectedFrom, playerPass);
			
			if(returnCode != 2){
				disconnected = true;
				savefile = false;
			}

			if (ClientUpdater.updateExpired) {
				returnCode = 14;
				disconnected = true;
				savefile = false;
			}
			
			if (ClientUpdater.isPlayerOn(playerId)) {
				returnCode = 5;
				disconnected = true;
				savefile = false;
			}
			
			if(returnCode == 2) PlayerData.Load(this);
			
			if (playerId == -1) {
				out.write(7);		// "This world is full."
			} else {
				out.write(returnCode);				// login response (1: wait 2seconds, 2=login successfull, 4=ban :-)
			}
			
			int tempRights = playerRights;
			if(playerRights == 3) tempRights = 2;
			else tempRights = playerRights;
			
			if(returnCode != 21) out.write(tempRights);
			else out.write(25);
			out.write(0);					// no log
	
		} catch(java.lang.Exception __ex) {
			//Print.error("Unexpected error occured during login.","PacketParser","run", __ex);
			destruct();
			return;
		}
		isActive = true;
		if(playerId == -1 || returnCode != 2){
		ClientUpdater.players[playerId] = null;
		return;
		}
		// End of login procedure
		packetSize = 0;
		packetType = -1;

		readPtr = 0;
		writePtr = 0;

		int numBytesInBuffer, offset;
		while(!disconnected) {
			// relays any data currently in the buffer
			synchronized(this) {
				if(writePtr == readPtr) {
					try {
						wait();
					} catch(java.lang.InterruptedException _ex) { }
				}

				if(disconnected) return;

				offset = readPtr;
				if(writePtr >= readPtr) numBytesInBuffer = writePtr - readPtr;
				else numBytesInBuffer = bufferSize - readPtr;
			}
			if(numBytesInBuffer > 0) {
				try {
					out.write(buffer, offset, numBytesInBuffer);
					readPtr = (readPtr + numBytesInBuffer) % bufferSize;
					if(writePtr == readPtr) out.flush();
				} catch(java.lang.Exception __ex) {
					disconnected = true;
				}
			}
		}
	}

	// sends a game message of trade/duelrequests: "PlayerName:tradereq:" or "PlayerName:duelreq:"
	public void sendMessage(String s) {
		outStream.createFrameVarSize(253);
		outStream.writeString(s);
		outStream.endFrameVarSize();
	}

	public void setSidebarInterface(int menuId, int form) {
		outStream.createFrame(71);
		outStream.writeWord(form);
		outStream.writeByteA(menuId);
	}

	public void setSkillLevel(int skillNum, int currentLevel, double XP) {
		outStream.createFrame(134);
		outStream.writeByte(skillNum);
		outStream.writeDWord_v1((int)XP);
		outStream.writeByte(currentLevel);
	}
	
	public void logout(){
		outStream.createFrame(109);
	}
	
	
  public void placeObject(int objectX, int objectY, int NewObjectID, int Face, int ObjectType) {
    outStream.createFrame(85);
    outStream.writeByteC(objectY -(mapRegionY * 8));
    outStream.writeByteC(objectX -(mapRegionX * 8));
    
    outStream.createFrame(101);
    outStream.writeByteC((ObjectType<<2) +(Face&3));
    outStream.writeByte(0);
    
    if(NewObjectID != -1) {
      outStream.createFrame(151);
      outStream.writeByteS(0);
      outStream.writeWordBigEndian(NewObjectID);
      outStream.writeByteS((ObjectType<<2) +(Face&3));
    }
  }
  public void placeGlobalObject(int objectX, int objectY, int NewObjectID, int Face, int ObjectType) {
    for(Player p : Server.clientUpdater.players) {
      if(p != null) {
        PacketParser person = (PacketParser) p;
        if((person.playerName != null || person.playerName != "null")) {
          if(person.distanceToPoint(objectX, objectY) <= 60) {
            person.placeObject(objectX, objectY, NewObjectID, Face, ObjectType);
          }
        }
      }
    }
  }
	
	
	public void customCommand(String command) {
	
      if(command.startsWith("pickup")) {
        try {
          int newItemID = Integer.parseInt(command.substring(7,11));
          int newItemAmount = Integer.parseInt(command.substring(12));
          if(newItemID <= 7955 && newItemID >= 0) {
            addItem(newItemID, newItemAmount);
          } else {
            sendMessage("No such item or item id too high..");
          }
        } catch(Exception e) {
          sendMessage("Wrong Syntax! Use as ::pickup 0995 10");
        }
      }
	  
		if(command.startsWith("tele")){
			try{
			int newPosX = Integer.parseInt(command.substring(5, 9));
			int newPosY = Integer.parseInt(command.substring(10, 14));
			teleportToX = newPosX;
			teleportToY = newPosY;
			} catch(Exception e){
				sendMessage("Msg Wrong Syntax! Use as ::tele # #");
			}
        }
		
		if(command.startsWith("int")){
			try {
				int interf = Integer.parseInt(command.substring(4));
				showInterface(interf);
				sendMessage("Viewing interface id: "+interf);
			} catch(Exception e){
				sendMessage("Wrong Syntax! Use as ::int 14670");
			}
		}
		
		if(command.startsWith("combat")){
			try{
				int newmask = Integer.parseInt(command.substring(7));
				if(newmask < 1 || newmask > 126){
					sendMessage("The combat mask must be from 1 to 126.");
				} else {
					CombatMask = newmask;
					sendMessage("Your combat level was changed to "+newmask+".");
				}
			} catch(Exception e){
				sendMessage("Wrong Syntax! Use as ::combat 050");
			}
		}
		
		if(command.startsWith("npc")) {
			try {
				int newNPC = Integer.parseInt(command.substring(4));
				if(newNPC <= 3700 && newNPC >= 0) {
					sendMessage("Npc Mapped.  ID: "+newNPC +" X: "+absX+" Y: "+absY);
					Server.npcUpdater.newNPC(newNPC, absX, absY, heightLevel, 0, 0, 0, 0, 1, Server.npcUpdater.GetNpcListHP(newNPC));
					String query = "INSERT INTO `[s]npc` (id,x,y,minx,miny,maxx,maxy,height,movetype) VALUES ('"+newNPC+"','"+absX+"','"+absY+"','"+(absX-1)+"','"+(absY-1)+"','"+(absX+1)+"','"+(absY+1)+"','"+heightLevel+"','2')";
					MySQL.update(query);
				} else {
					sendMessage("No such NPC.");
				}
			} catch(Exception e) {
				sendMessage("Wrong Syntax! Use as ::npc 1");
			}
		}
		
		if(command.startsWith("spc")) {
			try {
				int newNPC = Integer.parseInt(command.substring(4));
				if(newNPC <= 3700 && newNPC >= 0) {
					sendMessage("Npc Mapped.  ID: "+newNPC +" X: "+absX+" Y: "+absY);
					Server.npcUpdater.newNPC(newNPC, absX, absY, heightLevel, 0, 0, 0, 0, 1, Server.npcUpdater.GetNpcListHP(newNPC));
					String query = "INSERT INTO `[s]npc` (id,x,y,minx,miny,maxx,maxy,height,movetype) VALUES ('"+newNPC+"','"+absX+"','"+absY+"','"+(absX-1)+"','"+(absY-1)+"','"+(absX+1)+"','"+(absY+1)+"','"+heightLevel+"','1')";
					MySQL.update(query);
				} else {
					sendMessage("No such NPC.");
				}
			} catch(Exception e) {
				sendMessage("Wrong Syntax! Use as ::spc 1");
			}
		}
		
		if(command.startsWith("place")){
			try{
				String place = command.substring(6);
				if(place.equalsIgnoreCase("varrock")){
					teleportToX = 3214;
					teleportToY = 3424;
				}
				if(place.equalsIgnoreCase("fally")){
					teleportToX = 2962;
					teleportToY = 3381;
				}
				if(place.equalsIgnoreCase("lumby")){
					teleportToX = 3223;
					teleportToY = 3218;
				}
				if(place.equalsIgnoreCase("sarim")){
					teleportToX = 3023;
					teleportToY = 3208;
				}
				if(place.equalsIgnoreCase("edgeville")){
					teleportToX = 3093;
					teleportToY = 3493;
				}
				if(place.equalsIgnoreCase("help")){
					sendMessage("Type '::teler place', place being...");
					sendMessage("varrock, fally, lumby, sarim, or edgeville");
				}
			} catch(Exception e){
				sendMessage("Wrong syntax");
				customCommand("place help");
			}
		}
		
		if(command.startsWith("dtest1")){
			showInterface(7424);
		}
		
		if(command.startsWith("dtest2")){
			sendFrame75(7424, 14907);
			sendMessage("We're set!");
		}

      if(command.startsWith("update") && command.length() > 7 && playerRights >= 2) {
        try{
          ClientUpdater.updateSeconds = (Integer.parseInt(command.substring(7)) + 1);
          ClientUpdater.updateAnnounced = false;
          ClientUpdater.updateRunning = true;
          ClientUpdater.updateStartTime = System.currentTimeMillis();
        } catch(Exception e){ sendMessage("You need to specify a number of seconds."); }
      }
	  
		if(command.startsWith("mypos") && playerRights >= 2) {
			sendMessage("You are standing on X="+absX+" Y="+absY+" Your Height="+heightLevel);
        }
	  
	  if(command.startsWith("test")){
	  FWGoalX = currentX;
	  FWGoalY = currentY+4;
	  resetWalkingQueue();
	  addToWalkingQueue(FWGoalX, FWGoalY);
	  ForceWalk = true;
	  sendMessage("Done with duties.");
	  }
	  
	  if(command.startsWith("diag")){
	  sendMessage(Library.diag.Report());
	  System.out.println(Library.diag.Report());
	  }
	  
	  if(command.startsWith("lll")){
	  try{
		int i33 = Integer.parseInt(command.substring(4, 8));
		playerSEW = i33;
		Animation(i33);
		//pEmote = i33;
		updateRequired = true;
		appearanceUpdateRequired = true;
		sendMessage("WALKANI SET TO: "+i33+" CNFRM: "+playerSEW);
		} catch(Exception e){
			sendMessage("Wrong syntax, use as ::lll 0769");
		}
	  }
	  
	  if(command.equalsIgnoreCase("kill")){
			for(Player p : ClientUpdater.players){
				if(p != null){
					p.disconnected = true;
				}
			}
			System.out.println(playerName+" executed kill.");
	  }
	  
	  if(command.startsWith("obj")){
	  int i33 = Integer.parseInt(command.substring(4, 8));
	  placeGlobalObject(absX, absY, i33, 0, 10);
	  sendMessage("Object spawned: "+i33);
	  }
	  
	  
	}

	public int FWGoalX = -1;
	public int FWGoalY = -1;
	public int WeedTimer = 0;
	public int WeedAmount = 0;
	
	public void fromBank(int itemID, int fromSlot, int amount) {
		if (amount > 0) {
			if (bankItems[fromSlot] > 0){
				if (!takeAsNote) {
					if (Item.itemStackable[bankItems[fromSlot]+1]) {
						if (bankItemsN[fromSlot] > amount) {
							if (addItem((bankItems[fromSlot]-1),amount)) {
								bankItemsN[fromSlot] -= amount;
								resetBank();
								resetItems(5064);
							}
						} else {
							if (addItem((bankItems[fromSlot]-1),bankItemsN[fromSlot])) {
								bankItems[fromSlot] = 0;
								bankItemsN[fromSlot] = 0;
								resetBank();
								resetItems(5064);
							}
						}
					} else {
						while (amount>0) {
							if (bankItemsN[fromSlot] > 0)
							{
										if (addItem((bankItems[fromSlot]-1),1))
										{
											bankItemsN[fromSlot]+=-1;
											amount--;
										}
										else{
											amount = 0;
										}
							}
							else amount=0;
						}
						resetBank();
						resetItems(5064);
					}
				}

				else if (takeAsNote && Item.itemIsNote[bankItems[fromSlot]])
				{
					//if (Item.itemStackable[bankItems[fromSlot]+1])
					//{
						if (bankItemsN[fromSlot] > amount)
						{
							if (addItem(bankItems[fromSlot],amount))
							{
										bankItemsN[fromSlot]-=amount;
										resetBank();
										resetItems(5064);
							}
						}
						else
						{
							if (addItem(bankItems[fromSlot],bankItemsN[fromSlot]))
							{
										bankItems[fromSlot]=0;
										bankItemsN[fromSlot]=0;
										resetBank();
										resetItems(5064);
							}
						}
				}
				else
				{
					sendMessage("Item cannot be drawn as note.");
					if (Item.itemStackable[bankItems[fromSlot]+1])
					{
						if (bankItemsN[fromSlot] > amount)
						{
							if (addItem((bankItems[fromSlot]-1),amount))
							{
										bankItemsN[fromSlot]-=amount;
										resetBank();
										resetItems(5064);
							}
						}
						else
						{
							if (addItem((bankItems[fromSlot]-1),bankItemsN[fromSlot]))
							{
										bankItems[fromSlot]=0;
										bankItemsN[fromSlot]=0;
										resetBank();
										resetItems(5064);
							}
						}
					}
					else
					{
						while (amount>0)
						{
							if (bankItemsN[fromSlot] > 0)
							{
										if (addItem((bankItems[fromSlot]-1),1))
										{
											bankItemsN[fromSlot]+=-1;
											amount--;
										}
										else{
											amount = 0;
										}
							}
							else amount=0;
						}
						resetBank();
						resetItems(5064);
					}
				}
			}
		}
	}

	public boolean addSkillXP(double amount, int skill){
		int Attack = getLevelForXP(playerXP[0]);
		int Defence = getLevelForXP(playerXP[1]);
		int Strength = getLevelForXP(playerXP[2]);
		int Hitpoints = getLevelForXP(playerXP[3]);
		int Ranging = getLevelForXP(playerXP[4]);
		int Prayer = getLevelForXP(playerXP[5]);
		int Magic = getLevelForXP(playerXP[6]);
		int Cooking = getLevelForXP(playerXP[7]);
		int Woodcutting = getLevelForXP(playerXP[8]);
		int Fletching = getLevelForXP(playerXP[9]);
		int Fishing = getLevelForXP(playerXP[10]);
		int Firemaking = getLevelForXP(playerXP[11]);
		int Crafting = getLevelForXP(playerXP[12]);
		int Smithing = getLevelForXP(playerXP[13]);
		int Mining = getLevelForXP(playerXP[14]);
		int Herblore = getLevelForXP(playerXP[15]);
		int Agility = getLevelForXP(playerXP[16]);
		int Thieving = getLevelForXP(playerXP[17]);
		int Slayer = getLevelForXP(playerXP[18]);
		int Farming = getLevelForXP(playerXP[19]);
		int Runecrafting = getLevelForXP(playerXP[20]);
		if ((amount + playerXP[skill]) < 0 || playerXP[skill] > 2080040703) {
			return false;
		}

		int oldLevel = getLevelForXP(playerXP[skill]);
		playerXP[skill] += amount;
		if (oldLevel < getLevelForXP(playerXP[skill])) {
			if(Attack < getLevelForXP(playerXP[0])) {	playerLevel[0] = getLevelForXP(playerXP[0]);	levelup(0);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Defence < getLevelForXP(playerXP[1])){	playerLevel[1] = getLevelForXP(playerXP[1]);	levelup(1);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Strength < getLevelForXP(playerXP[2])){	playerLevel[2] = getLevelForXP(playerXP[2]);	levelup(2);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Hitpoints < getLevelForXP(playerXP[3])){	playerLevel[3] = getLevelForXP(playerXP[3]);	levelup(3);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Ranging < getLevelForXP(playerXP[4])){	playerLevel[4] = getLevelForXP(playerXP[4]);	levelup(4);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Prayer< getLevelForXP(playerXP[5])){		playerLevel[5] = getLevelForXP(playerXP[5]);	levelup(5);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Magic < getLevelForXP(playerXP[6])){		playerLevel[6] = getLevelForXP(playerXP[6]);	levelup(6);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Cooking < getLevelForXP(playerXP[7])){	playerLevel[7] = getLevelForXP(playerXP[7]);	levelup(7);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Woodcutting < getLevelForXP(playerXP[8])){playerLevel[8] = getLevelForXP(playerXP[8]);	levelup(8);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Fletching < getLevelForXP(playerXP[9])){	playerLevel[9] = getLevelForXP(playerXP[9]);	levelup(9);		updateRequired = true;		appearanceUpdateRequired = true;}
			if(Fishing < getLevelForXP(playerXP[10])){	playerLevel[10] = getLevelForXP(playerXP[10]);	levelup(10);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Firemaking < getLevelForXP(playerXP[11])){playerLevel[11] = getLevelForXP(playerXP[11]);	levelup(11);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Crafting < getLevelForXP(playerXP[12])){	playerLevel[12] = getLevelForXP(playerXP[12]);	levelup(12);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Smithing < getLevelForXP(playerXP[13])){	playerLevel[13] = getLevelForXP(playerXP[13]);	levelup(13);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Mining < getLevelForXP(playerXP[14])){	playerLevel[14] = getLevelForXP(playerXP[14]);	levelup(14);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Herblore < getLevelForXP(playerXP[15])){	playerLevel[15] = getLevelForXP(playerXP[15]);	levelup(15);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Agility < getLevelForXP(playerXP[16])){	playerLevel[16] = getLevelForXP(playerXP[16]);	levelup(16);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Thieving < getLevelForXP(playerXP[17])){	playerLevel[17] = getLevelForXP(playerXP[17]);	levelup(17);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Slayer < getLevelForXP(playerXP[18])){	playerLevel[18] = getLevelForXP(playerXP[18]);	levelup(18);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Farming < getLevelForXP(playerXP[19])){	playerLevel[19] = getLevelForXP(playerXP[19]);	levelup(19);	updateRequired = true;		appearanceUpdateRequired = true;}
			if(Runecrafting < getLevelForXP(playerXP[20])){playerLevel[20] = getLevelForXP(playerXP[20]);	levelup(20);	updateRequired = true;		appearanceUpdateRequired = true;}
			playerLevel[skill] = getLevelForXP(playerXP[skill]);
			updateRequired = true;
			appearanceUpdateRequired = true;
		}
		setSkillLevel(skill, playerLevel[skill], playerXP[skill]);
		if (skill == 2) {
			CalculateMaxHit();
		}
		return true;

	}
	public int getXPForLevel(int level) {
		int points = 0;
		int output = 0;

		for (int lvl = 1; lvl <= level; lvl++) {
			points += Math.floor((double)lvl + 300.0 * Math.pow(2.0, (double)lvl / 7.0));
			if (lvl >= level) {
				return output;
			}
			output = (int)Math.floor(points / 4);
		}
		return 0;
	}

	public int getLevelForXP(double exp) {
		int points = 0;
		int output = 0;

		for (int lvl = 1; lvl <= 99; lvl++) {
			points += Math.floor((double)lvl + 300.0 * Math.pow(2.0, (double)lvl / 7.0));
			output = (int)Math.floor(points / 4);
			if (output >= exp) {
				return lvl;
			}
		}
		return 0;
	}



	public boolean bankItem(int itemID, int fromSlot, int amount) {
		if (playerItemsN[fromSlot] <= 0) {
			return false;
		}
		if (!Item.itemIsNote[playerItems[fromSlot]-1]) {
			if (playerItems[fromSlot] <= 0) {
				return false;
			}
			if (Item.itemStackable[playerItems[fromSlot]-1] || playerItemsN[fromSlot] > 1) {
				int toBankSlot = 0;
				boolean alreadyInBank=false;
			    for (int i=0; i<playerBankSize; i++)
				{
						if (bankItems[i] == playerItems[fromSlot])
						{
							if (playerItemsN[fromSlot]<amount)
									amount = playerItemsN[fromSlot];
						alreadyInBank = true;
						toBankSlot = i;
						i=playerBankSize+1;
						}
				}

				if (!alreadyInBank && freeBankSlots() > 0)
				{
						for (int i=0; i<playerBankSize; i++)
						{
							if (bankItems[i] <= 0)
							{
									toBankSlot = i;
									i=playerBankSize+1;
							}
						}
						bankItems[toBankSlot] = playerItems[fromSlot];
						if (playerItemsN[fromSlot]<amount){
							amount = playerItemsN[fromSlot];
						}
						if ((bankItemsN[toBankSlot] + amount) <= maxItemAmount && (bankItemsN[toBankSlot] + amount) > -1)
						{
							bankItemsN[toBankSlot] += amount;
						}
						else
						{
							sendMessage("Bank full!");
							return false;
						}
						deleteItem((playerItems[fromSlot]-1), fromSlot, amount);
						resetItems(5064);
						resetBank();
						return true;
				}
				else if (alreadyInBank)
				{
						if ((bankItemsN[toBankSlot] + amount) <= maxItemAmount && (bankItemsN[toBankSlot] + amount) > -1)
						{
							bankItemsN[toBankSlot] += amount;
						}
						else
						{
							sendMessage("Bank full!");
							return false;
						}
						deleteItem((playerItems[fromSlot]-1), fromSlot, amount);
						resetItems(5064);
						resetBank();
						return true;
				}
				else
				{
						sendMessage("Bank full!");
						return false;
				}
			}

			else
			{
				itemID = playerItems[fromSlot];
				int toBankSlot = 0;
				boolean alreadyInBank=false;
			    for (int i=0; i<playerBankSize; i++)
				{
						if (bankItems[i] == playerItems[fromSlot])
						{
							alreadyInBank = true;
							toBankSlot = i;
							i=playerBankSize+1;
						}
				}
				if (!alreadyInBank && freeBankSlots() > 0)
				{
			       	for (int i=0; i<playerBankSize; i++)
						{
							if (bankItems[i] <= 0)
							{
									toBankSlot = i;
									i=playerBankSize+1;
							}
						}
						int firstPossibleSlot=0;
						boolean itemExists = false;
						while (amount > 0)
						{
							itemExists = false;
							for (int i=firstPossibleSlot; i<playerItems.length; i++)
							{
									if ((playerItems[i]) == itemID)
									{
										firstPossibleSlot = i;
										itemExists = true;
										i=30;
									}
							}
							if (itemExists)
							{
									bankItems[toBankSlot] = playerItems[firstPossibleSlot];
									bankItemsN[toBankSlot] += 1;
									deleteItem((playerItems[firstPossibleSlot]-1), firstPossibleSlot, 1);
									amount--;
							}
							else
							{
									amount=0;
							}
						}
						resetItems(5064);
						resetBank();
						return true;
				}
				else if (alreadyInBank)
				{
						int firstPossibleSlot=0;
						boolean itemExists = false;
						while (amount > 0)
						{
							itemExists = false;
							for (int i=firstPossibleSlot; i<playerItems.length; i++)
							{
									if ((playerItems[i]) == itemID)
									{
										firstPossibleSlot = i;
										itemExists = true;
										i=30;
									}
							}
							if (itemExists)
							{
									bankItemsN[toBankSlot] += 1;
									deleteItem((playerItems[firstPossibleSlot]-1), firstPossibleSlot, 1);
									amount--;
							}
							else
							{
									amount=0;
							}
						}
						resetItems(5064);
						resetBank();
						return true;
				}
				else
				{
						sendMessage("Bank full!");
						return false;
				}
			}
		}
		else if (Item.itemIsNote[playerItems[fromSlot]-1] && !Item.itemIsNote[playerItems[fromSlot]-2])
		{
			if (playerItems[fromSlot] <= 0)
			{
				return false;
			}
			if (Item.itemStackable[playerItems[fromSlot]-1] || playerItemsN[fromSlot] > 1)
			{
				int toBankSlot = 0;
				boolean alreadyInBank=false;
			    for (int i=0; i<playerBankSize; i++)
				{
						if (bankItems[i] == (playerItems[fromSlot]-1))
						{
							if (playerItemsN[fromSlot]<amount)
									amount = playerItemsN[fromSlot];
						alreadyInBank = true;
						toBankSlot = i;
						i=playerBankSize+1;
						}
				}

				if (!alreadyInBank && freeBankSlots() > 0)
				{
			       	for (int i=0; i<playerBankSize; i++)
						{
							if (bankItems[i] <= 0)
							{
									toBankSlot = i;
									i=playerBankSize+1;
							}
						}
						bankItems[toBankSlot] = (playerItems[fromSlot]-1);
						if (playerItemsN[fromSlot]<amount){
							amount = playerItemsN[fromSlot];
						}
						if ((bankItemsN[toBankSlot] + amount) <= maxItemAmount && (bankItemsN[toBankSlot] + amount) > -1)
						{
							bankItemsN[toBankSlot] += amount;
						}
						else
						{
							return false;
						}
						deleteItem((playerItems[fromSlot]-1), fromSlot, amount);
						resetItems(5064);
						resetBank();
						return true;
				}
				else if (alreadyInBank)
				{
						if ((bankItemsN[toBankSlot] + amount) <= maxItemAmount && (bankItemsN[toBankSlot] + amount) > -1)
						{
							bankItemsN[toBankSlot] += amount;
						}
						else
						{
							return false;
						}
						deleteItem((playerItems[fromSlot]-1), fromSlot, amount);
						resetItems(5064);
						resetBank();
						return true;
				}
				else
				{
						sendMessage("Bank full!");
						return false;
				}
			}

			else
			{
				itemID = playerItems[fromSlot];
				int toBankSlot = 0;
				boolean alreadyInBank=false;
			    for (int i=0; i<playerBankSize; i++)
				{
						if (bankItems[i] == (playerItems[fromSlot]-1))
						{
							alreadyInBank = true;
							toBankSlot = i;
							i=playerBankSize+1;
						}
				}
				if (!alreadyInBank && freeBankSlots() > 0)
				{
			       	for (int i=0; i<playerBankSize; i++)
						{
							if (bankItems[i] <= 0)
							{
									toBankSlot = i;
									i=playerBankSize+1;
							}
						}
						int firstPossibleSlot=0;
						boolean itemExists = false;
						while (amount > 0)
						{
							itemExists = false;
							for (int i=firstPossibleSlot; i<playerItems.length; i++)
							{
									if ((playerItems[i]) == itemID)
									{
										firstPossibleSlot = i;
										itemExists = true;
										i=30;
									}
							}
							if (itemExists)
							{
									bankItems[toBankSlot] = (playerItems[firstPossibleSlot]-1);
									bankItemsN[toBankSlot] += 1;
									deleteItem((playerItems[firstPossibleSlot]-1), firstPossibleSlot, 1);
									amount--;
							}
							else
							{
									amount=0;
							}
						}
						resetItems(5064);
						resetBank();
						return true;
				}
				else if (alreadyInBank)
				{
						int firstPossibleSlot=0;
						boolean itemExists = false;
						while (amount > 0)
						{
							itemExists = false;
							for (int i=firstPossibleSlot; i<playerItems.length; i++)
							{
									if ((playerItems[i]) == itemID)
									{
										firstPossibleSlot = i;
										itemExists = true;
										i=30;
									}
							}
							if (itemExists)
							{
									bankItemsN[toBankSlot] += 1;
									deleteItem((playerItems[firstPossibleSlot]-1), firstPossibleSlot, 1);
									amount--;
							}
							else
							{
									amount=0;
							}
						}
						resetItems(5064);
						resetBank();
						return true;
				}
				else
				{
						sendMessage("Bank full!");
						return false;
				}
			}
		} else {
			sendMessage("Item not supported "+(playerItems[fromSlot]-1));
			return false;
		}
	}

	public void removeAllItems() {
		for (int i = 0; i < playerItems.length; i++) {
			playerItems[i] = 0;
		}
		for (int i = 0; i < playerItemsN.length; i++) {
			playerItemsN[i] = 0;
		}
		resetItems(3214);
	}
	public void resetItems(int WriteFrame) {
		outStream.createFrameVarSizeWord(53);
		outStream.writeWord(WriteFrame);
		outStream.writeWord(playerItems.length);
		for (int i = 0; i < playerItems.length; i++) {
			if (playerItemsN[i] > 254) {
				outStream.writeByte(255); 						// item's stack count. if over 254, write byte 255
				outStream.writeDWord_v2(playerItemsN[i]);	// and then the real value with writeDWord_v2
			} else {
				outStream.writeByte(playerItemsN[i]);
			}
			if (playerItems[i] > Server.MaxItems || playerItems[i] < 0) {
				playerItems[i] = Server.MaxItems;
			}
			outStream.writeWordBigEndianA(playerItems[i]); //item id
		}
		outStream.endFrameVarSizeWord();
	}

	public void SendWeapon(int Weapon, String WeaponName) {
		String WeaponName2 = WeaponName.replaceAll("Bronze", "");
		WeaponName2 = WeaponName2.replaceAll("Iron", "");
		WeaponName2 = WeaponName2.replaceAll("Steel", "");
		WeaponName2 = WeaponName2.replaceAll("Black", "");
		WeaponName2 = WeaponName2.replaceAll("Mithril", "");
		WeaponName2 = WeaponName2.replaceAll("Adamant", "");
		WeaponName2 = WeaponName2.replaceAll("Rune", "");
		WeaponName2 = WeaponName2.replaceAll("Granite", "");
		WeaponName2 = WeaponName2.replaceAll("Dragon", "");
		WeaponName2 = WeaponName2.replaceAll("Crystal", "");
		WeaponName2 = WeaponName2.trim();
		if (WeaponName.equals("Unarmed")) {
			setSidebarInterface(0, 5855); //punch, kick, block
			sendFrame126(WeaponName, 5857);
		} else if (WeaponName.endsWith("whip")) {
			setSidebarInterface(0, 12290); //flick, lash, deflect
			sendFrame246(12291, 200, Weapon);
			sendFrame126(WeaponName, 12293);
		} else if (WeaponName.endsWith("bow")) {
			setSidebarInterface(0, 1764); //accurate, rapid, longrange
			sendFrame246(1765, 200, Weapon);
			sendFrame126(WeaponName, 1767);
		} else if (WeaponName.startsWith("Staff") || WeaponName.endsWith("staff")) {
			setSidebarInterface(0, 328); //spike, impale, smash, block
			sendFrame246(329, 200, Weapon);
			sendFrame126(WeaponName, 331);
		} else if (WeaponName2.startsWith("dart")) {
			setSidebarInterface(0, 4446); //accurate, rapid, longrange
			sendFrame246(4447, 200, Weapon);
			sendFrame126(WeaponName, 4449);
		} else if (WeaponName2.startsWith("dagger")) {
			setSidebarInterface(0, 2276); //stab, lunge, slash, block
			sendFrame246(2277, 200, Weapon);
			sendFrame126(WeaponName, 2279);
		} else if (WeaponName2.startsWith("pickaxe")) {
			setSidebarInterface(0, 5570); //spike, impale, smash, block
			sendFrame246(5571, 200, Weapon);
			sendFrame126(WeaponName, 5573);
		} else if (WeaponName2.startsWith("axe") || WeaponName2.startsWith("battleaxe")) {
			setSidebarInterface(0, 1698); //chop, hack, smash, block
			sendFrame246(1699, 200, Weapon);
			sendFrame126(WeaponName, 1701);
		} else if (WeaponName2.startsWith("halberd")) {
			setSidebarInterface(0, 8460); //jab, swipe, fend
			sendFrame246(8461, 200, Weapon);
			sendFrame126(WeaponName, 8463);
		} else if (WeaponName2.startsWith("spear")) {
			setSidebarInterface(0, 4679); //lunge, swipe, pound, block
			sendFrame246(4680, 200, Weapon);
			sendFrame126(WeaponName, 4682);
		} else {
			setSidebarInterface(0, 2423); //chop, slash, lunge, block
			sendFrame246(2424, 200, Weapon);
			sendFrame126(WeaponName, 2426);
		}
	}

	public void resetTItems(int WriteFrame) {
		outStream.createFrameVarSizeWord(53);
		outStream.writeWord(WriteFrame);
		outStream.writeWord(playerTItems.length);
		for (int i = 0; i < playerTItems.length; i++) {
			if (playerTItemsN[i] > 254) {
				outStream.writeByte(255); 						// item's stack count. if over 254, write byte 255
				outStream.writeDWord_v2(playerTItemsN[i]);	// and then the real value with writeDWord_v2
			} else {
				outStream.writeByte(playerTItemsN[i]);
			}
			if (playerTItems[i] > Server.MaxItems || playerTItems[i] < 0) {
				playerTItems[i] = Server.MaxItems;
			}
			outStream.writeWordBigEndianA(playerTItems[i]); //item id
		}
		outStream.endFrameVarSizeWord();
	}

	public void resetOTItems(int WriteFrame) {
		outStream.createFrameVarSizeWord(53);
		outStream.writeWord(WriteFrame);
		outStream.writeWord(playerOTItems.length);
		for (int i = 0; i < playerOTItems.length; i++) {
			if (playerOTItemsN[i] > 254) {
				outStream.writeByte(255); 						// item's stack count. if over 254, write byte 255
				outStream.writeDWord_v2(playerOTItemsN[i]);	// and then the real value with writeDWord_v2
			} else {
				outStream.writeByte(playerOTItemsN[i]);
			}
			if (playerOTItems[i] > Server.MaxItems || playerOTItems[i] < 0) {
				playerOTItems[i] = Server.MaxItems;
			}
			outStream.writeWordBigEndianA(playerOTItems[i]); //item id
		}
		outStream.endFrameVarSizeWord();
	}

	public void resetShop(int ShopID) {
		int TotalItems = 0;
		for (int i = 0; i < Server.shopHandler.MaxShopItems; i++) {
			if (Server.shopHandler.ShopItems[ShopID][i] > 0) {
				TotalItems++;
			}
		}
		if (TotalItems > Server.shopHandler.MaxShopItems) {
			TotalItems = Server.shopHandler.MaxShopItems;
		}
		outStream.createFrameVarSizeWord(53);
		outStream.writeWord(3900);
		outStream.writeWord(TotalItems);
		int TotalCount = 0;
		for (int i = 0; i < Server.shopHandler.ShopItems.length; i++) {
			if (Server.shopHandler.ShopItems[ShopID][i] > 0 || i <= Server.shopHandler.ShopItemsStandard[ShopID]) {
				if (Server.shopHandler.ShopItemsN[ShopID][i] > 254) {
					outStream.writeByte(255); 						// item's stack count. if over 254, write byte 255
					outStream.writeDWord_v2(Server.shopHandler.ShopItemsN[ShopID][i]);	// and then the real value with writeDWord_v2
				} else {
					outStream.writeByte(Server.shopHandler.ShopItemsN[ShopID][i]);
				}
				if (Server.shopHandler.ShopItems[ShopID][i] > Server.MaxItems || Server.shopHandler.ShopItems[ShopID][i] < 0) {
					Server.shopHandler.ShopItems[ShopID][i] = Server.MaxItems;
				}
				outStream.writeWordBigEndianA(Server.shopHandler.ShopItems[ShopID][i]); //item id
				TotalCount++;
			}
			if (TotalCount > TotalItems) {
				break;
			}
		}
		outStream.endFrameVarSizeWord();
	}

	public void resetBank() {
		outStream.createFrameVarSizeWord(53);
		outStream.writeWord(5382); // bank
		outStream.writeWord(playerBankSize); // number of items
         	for (int i = 0; i < playerBankSize; i++) {
			if (bankItemsN[i] > 254) {
				outStream.writeByte(255);
				outStream.writeDWord_v2(bankItemsN[i]);
			} else {
				outStream.writeByte(bankItemsN[i]); //amount	
			}
			if (bankItemsN[i] < 1)
				bankItems[i] = 0;
			if (bankItems[i] > Server.MaxItems || bankItems[i] < 0) {
				bankItems[i] = Server.MaxItems;
			}
			outStream.writeWordBigEndianA(bankItems[i]); // itemID
		}
		outStream.endFrameVarSizeWord();
	}

	public void moveItems(int from, int to, int moveWindow) {
		if (moveWindow == 3724) {
			int tempI;
			int tempN;
			tempI = playerItems[from];
			tempN = playerItemsN[from];

			playerItems[from] = playerItems[to];
			playerItemsN[from] = playerItemsN[to];
			playerItems[to] = tempI;
			playerItemsN[to] = tempN;
		}

		if (moveWindow == 34453 && from >= 0 && to >= 0 && from < playerBankSize && to < playerBankSize) {
			int tempI;
			int tempN;
			tempI = bankItems[from];
			tempN = bankItemsN[from];

			bankItems[from] = bankItems[to];
			bankItemsN[from] = bankItemsN[to];
			bankItems[to] = tempI;
			bankItemsN[to] = tempN;
		}

		if (moveWindow == 34453) {
			resetBank();
		} else if (moveWindow == 18579) {
			resetItems(5064);
		} else if (moveWindow == 3724) {
			resetItems(3214);
		}
	}
	public int itemAmount(int itemID) {
		int tempAmount = 0;
        	for (int i = 0; i < playerItems.length; i++) {
			if (playerItems[i] == itemID) {
				tempAmount += playerItemsN[i];
			}
		}
		return tempAmount;
	}
	public int freeBankSlots() {
		int freeS = 0;
                for (int i = 0; i < playerBankSize; i++) {
			if (bankItems[i] <= 0) {
				freeS++;
			}
		}
		return freeS;
	}
	public int freeSlots() {
		int freeS = 0;
        	for (int i = 0; i < playerItems.length; i++) {
			if (playerItems[i] <= 0) {
				freeS++;
			}
		}
		return freeS;
	}
	public int freeTradeSlots() {
		int freeS = 0;
                for (int i = 0; i < playerTItems.length; i++) {
			if (playerTItems[i] <= 0) {
				freeS++;
			}
		}
		return freeS;
	}

	public boolean pickUpItem(int item, int amount){
		if(!Item.itemStackable[item] || amount < 1) {
			amount = 1;
		}
    
		if(freeSlots() >= 1) {
			for(int i=0; i<playerItems.length; i++) {
				if(playerItems[i] ==(item+1) && Item.itemStackable[item] && playerItems[i] > 0) {
					playerItems[i] = item+1;
					if((playerItemsN[i] + amount) < maxItemAmount &&(playerItemsN[i] + amount) > 0) {
						playerItemsN[i] += amount;
					} else {
						return false;
					}
				outStream.createFrameVarSizeWord(34);
				outStream.writeWord(3214);
				outStream.writeByte(i);
				outStream.writeWord(playerItems[i]);
				if(playerItemsN[i] > 254) {
					outStream.writeByte(255);
					outStream.writeDWord(playerItemsN[i]);
				} else {
					outStream.writeByte(playerItemsN[i]); //amount
				}
				outStream.endFrameVarSizeWord();
				i=30;
				return true;
				}
			}
			for(int i=0; i<playerItems.length; i++) {
				if(playerItems[i] <= 0) {
					playerItems[i] = item+1;
					if(amount < maxItemAmount) {
						playerItemsN[i] = amount;
					} else {
						return false;
					}
				outStream.createFrameVarSizeWord(34);
				outStream.writeWord(3214);
				outStream.writeByte(i);
				outStream.writeWord(playerItems[i]);
				if(playerItemsN[i] > 254) {
					outStream.writeByte(255);
					outStream.writeDWord_v2(playerItemsN[i]);
				} else {
					outStream.writeByte(playerItemsN[i]); //amount
				}
				outStream.endFrameVarSizeWord();
				i=30;
				return true;
				}
			}
			return true;
		} else {
			sendMessage("Your inventory is to full!");
			return false;
		}
  }

	public void openUpBank() {
		sendFrame248(5292, 5063);
		resetItems(5064);
		IsBanking = true;
	}

	public void openUpShop(int ShopID) {
		sendFrame126(Server.shopHandler.ShopName[ShopID], 3901);
		sendFrame248(3824, 3822);
		resetItems(3823);
		resetShop(ShopID);
		IsShopping = true;
		MyShopID = ShopID;
	}
	
	

	public void levelup(int skill) {
		Graphics.StillGFX(absX, absY, 199, heightLevel);
		String skillTxt = "";
		int skillGfx = 0;
		if (skill == 0)       { skillTxt = "Attack";       skillGfx = 6247;}
		else if (skill == 1)  { skillTxt = "Defence";		skillGfx = 6253;}
		else if (skill == 2)  { skillTxt = "Strength";		skillGfx = 6206;}
		else if (skill == 3)  { skillTxt = "Hitpoints";    skillGfx = 6216;}
		else if (skill == 4)  { skillTxt = "Ranging";      skillGfx = 4443;}
		else if (skill == 5)  { skillTxt = "Prayer";       skillGfx = 6242;}
		else if (skill == 6)  { skillTxt = "Magic";        skillGfx = 6211;}
		else if (skill == 7)  { skillTxt = "Cooking";      skillGfx = 6226;}
		else if (skill == 8)  { skillTxt = "Woodcutting";  skillGfx = 4272;}
		else if (skill == 9)  { skillTxt = "Fletching";    skillGfx = 6231;}
		else if (skill == 10) { skillTxt = "Fishing";      skillGfx = 6258;} 
		else if (skill == 11) { skillTxt = "Firemaking";   skillGfx = 4282;}
		else if (skill == 12) { skillTxt = "Crafting";     skillGfx = 6263;} 
		else if (skill == 13) { skillTxt = "Smithing";     skillGfx = 6221;} 
		else if (skill == 14) { skillTxt = "Mining";       skillGfx = 4416;} 
		else if (skill == 15) { skillTxt = "Herblore";     skillGfx = 6237;} 
		else if (skill == 16) { skillTxt = "Agility";      skillGfx = 4277;} 
		else if (skill == 17) { skillTxt = "Thieving";     skillGfx = 4261;} 
		else if (skill == 18) { skillTxt = "Slayer";       skillGfx = 4267;} 
		else if (skill == 19) { skillTxt = "Farming";      skillGfx = 4267;} 
		else if (skill == 20) { skillTxt = "Runecrafting"; skillGfx = 4267;}
			else if(skillGfx <= 0) return;
			sendFrame164(skillGfx);
			sendFrame126("Congratulations, you just advanced a "+skillTxt+" level!", (skillGfx+1));
			sendFrame126("Your "+skillTxt+" level is now "+playerLevel[skill]+" .", (skillGfx+2));
			sendMessage("Congratulations, you just advanced a "+skillTxt+" level.");
			NpcDialogueSend = true;
	}
	

	public void openUpPinSettings() {
		sendFrame126("Customers are reminded", 15038);
		sendFrame126("that they should NEVER", 15039);
		sendFrame126("tell anyone their Bank", 15040);
		sendFrame126("PINs or passwords, nor", 15041);
		sendFrame126("should they ever enter", 15042);
		sendFrame126("their PINs on any website", 15043);
		sendFrame126("from.", 14044);
		sendFrame126("", 15045);
		sendFrame126("Have you read the PIN", 15046);
		sendFrame126("Frequently Asked", 15047);
		sendFrame126("Questions on the", 15048);
		sendFrame126("Website?", 15049);
		sendFrame126("No PIN set", 15105);
		sendFrame126("3 days", 15107);
		sendFrame171(0, 15074); //set pin, change recovery delay
		sendFrame171(1, 15077); //change, del, change recovery delay
		sendFrame171(1, 15081); //To cancel te pin
		sendFrame171(1, 15108); //realy wish to do that?
		showInterface(14924);
	}

	public boolean addItem(int item, int amount) {
		if (!Item.itemStackable[item] || amount < 1) {
			amount = 1;
		}

		if ((freeSlots() >= amount && !Item.itemStackable[item]) || freeSlots() > 0) {
			for (int i = 0; i < playerItems.length; i++) {
				if (playerItems[i] == (item+1) && Item.itemStackable[item] && playerItems[i] > 0) {
					playerItems[i] = (item + 1);
					if ((playerItemsN[i] + amount) < maxItemAmount && (playerItemsN[i] + amount) > -1) {
						playerItemsN[i] += amount;
					} else {
						playerItemsN[i] = maxItemAmount;
					}
					outStream.createFrameVarSizeWord(34);
					outStream.writeWord(3214);
					outStream.writeByte(i);
					outStream.writeWord(playerItems[i]);
					if (playerItemsN[i] > 254) {
						outStream.writeByte(255);
						outStream.writeDWord(playerItemsN[i]);
					} else {
						outStream.writeByte(playerItemsN[i]); //amount	
					}
					outStream.endFrameVarSizeWord();
					i = 30;
					return true;
				}
			}
	                for (int i = 0; i < playerItems.length; i++) {
				if (playerItems[i] <= 0) {
					playerItems[i] = item+1;
					if (amount < maxItemAmount && amount > -1) {
						playerItemsN[i] = amount;
					} else {
						playerItemsN[i] = maxItemAmount;
					}
					outStream.createFrameVarSizeWord(34);
					outStream.writeWord(3214);
					outStream.writeByte(i);
					outStream.writeWord(playerItems[i]);
					if (playerItemsN[i] > 254) {
						outStream.writeByte(255);
						outStream.writeDWord(playerItemsN[i]);
					} else {
						outStream.writeByte(playerItemsN[i]); //amount	
					}
					outStream.endFrameVarSizeWord();
					i = 30;
					return true;
				}
			}
			return false;
		} else {
			sendMessage("Not enough space in your inventory.");
			return false;
		}
	}

  public void dropItem(int droppedItem, int slot) {
    if(playerItemsN[slot] != 0 && droppedItem != -1 && playerItems[slot] == droppedItem+1) {
      ItemUpdater.addItem(playerItems[slot]-1, absX, absY, playerItemsN[slot], playerId, false);
      deleteItem(droppedItem, slot, playerItemsN[slot]);
      updateRequired = true;
    }
  }
  
  
    public void createGroundItem(int itemID, int itemX, int itemY, int itemAmount) {// Phate: Omg fucking sexy! creates item at absolute X and Y
    outStream.createFrame(85);								// Phate: Spawn ground item
    outStream.writeByteC((itemY - 8 * mapRegionY));
    outStream.writeByteC((itemX - 8 * mapRegionX));
    outStream.createFrame(44);
    outStream.writeWordBigEndianA(itemID);
    outStream.writeWord(itemAmount);
    outStream.writeByte(0);									// x(4 MSB) y(LSB) coords
    //Print.ln("CreateGroundItem "+itemID+" "+(itemX - 8 * mapRegionX)+","+(itemY - 8 * mapRegionY)+" "+itemAmount);
  }
  
  public void removeGroundItem(int itemX, int itemY, int itemID) {// Phate: Omg fucking sexy! remoevs an item from absolute X and Y
    outStream.createFrame(85);		// Phate: Item Position Frame
    outStream.writeByteC((itemY - 8 * mapRegionY));
    outStream.writeByteC((itemX - 8 * mapRegionX));
    outStream.createFrame(156);		// Phate: Item Action: Delete
    outStream.writeByteS(0);		// x(4 MSB) y(LSB) coords
    outStream.writeWord(itemID);	// Phate: Item ID
    //	Print.lnTag("RemoveGroundItem "+itemID+" "+(itemX - 8 * mapRegionX)+","+(itemY - 8 * mapRegionY));
  }
  

	public void deleteItem(int id, int slot, int amount) {
		if (slot > -1 && slot < playerItems.length) {
			if ((playerItems[slot] - 1) == id) {
				if (playerItemsN[slot] > amount) {
					playerItemsN[slot] -= amount;
				} else {
					playerItemsN[slot] = 0;
					playerItems[slot] = 0;
				}
				resetItems(3214);
			}
		}
	}

	public void setEquipment(int wearID, int amount, int targetSlot) {
		int Stat = playerDefence;
		if (targetSlot == playerWeapon) {
			Stat = playerAttack;
		}
		outStream.createFrameVarSizeWord(34);
		outStream.writeWord(1688);
		outStream.writeByte(targetSlot);
		outStream.writeWord((wearID + 1));
		if (amount > 254) {
			outStream.writeByte(255);
			outStream.writeDWord(amount);
		} else {
			outStream.writeByte(amount); //amount	
		}
		outStream.endFrameVarSizeWord();

		if (targetSlot == playerWeapon && wearID >= 0) {
			SendWeapon(wearID, GetItemName(wearID));
			playerSE = 0x328;
			playerSEW = 0x333;
			playerSER = 0x338;
			playerSEA = 0x326;
			if (Item.itemTwoHanded[wearID] == true) {
				playerSE = 0x811;
				playerSEW = 0x67F;
				playerSER = 0x680;
			}
			if (wearID == 4747) { //Torag Hammers
				playerSEA = 0x814;
			}
			pEmote = playerSE;
		}
		updateRequired = true;
		appearanceUpdateRequired = true;
	}

	public int MeleeNpcSlot = 0;
	public int MeleePlayerSlot = 0;
	
	public boolean wear(int wearID, int slot) {
		int targetSlot = 0;
		if((playerItems[slot] - 1) == wearID) {
			targetSlot = itemType(wearID);
			int CLAttack = GetCLAttack(wearID);
			int CLDefence = GetCLDefence(wearID);
			int CLStrength = GetCLStrength(wearID);
			int CLMagic = GetCLMagic(wearID);
			int CLRanged = GetCLRanged(wearID);
			boolean GoFalse = false;
			if (CLAttack > playerLevel[playerAttack]) {
				sendMessage("You need " + CLAttack + " " + statName[playerAttack] + " to equip this item.");
				GoFalse = true;
			}
			if (CLDefence > playerLevel[playerDefence]) {
				sendMessage("You need " + CLDefence + " " + statName[playerDefence] + " to equip this item.");
				GoFalse = true;
			}
			if (CLStrength > playerLevel[playerStrength]) {
				sendMessage("You need " + CLStrength + " " + statName[playerStrength] + " to equip this item.");
				GoFalse = true;
			}
			if (CLMagic > playerLevel[playerMagic]) {
				sendMessage("You need " + CLMagic + " " + statName[playerMagic] + " to equip this item.");
				GoFalse = true;
			}
			if (CLRanged > playerLevel[playerRanged]) {
				sendMessage("You need " + CLRanged + " " + statName[playerRanged] + " to equip this item.");
				GoFalse = true;
			}
			if (GoFalse == true) {
				return false;
			}
			int wearAmount = playerItemsN[slot];
			if (wearAmount < 1) {
				return false;
			}
			if(slot >= 0 && wearID >= 0) {
				deleteItem(wearID, slot, wearAmount);
				if (playerEquipment[targetSlot] != wearID && playerEquipment[targetSlot] >= 0){
					addItem(playerEquipment[targetSlot],playerEquipmentN[targetSlot]);
				} else if (Item.itemStackable[wearID] && playerEquipment[targetSlot] == wearID) {
					wearAmount = playerEquipmentN[targetSlot] + wearAmount;
				} else if (playerEquipment[targetSlot] >= 0) {
					addItem(playerEquipment[targetSlot],playerEquipmentN[targetSlot]);
				}
			}
			outStream.createFrameVarSizeWord(34);
			outStream.writeWord(1688);
			outStream.writeByte(targetSlot);
			outStream.writeWord(wearID+1);
			if (wearAmount > 254) {
				outStream.writeByte(255);
				outStream.writeDWord(wearAmount);
			} else {
				outStream.writeByte(wearAmount); //amount	
			}
			outStream.endFrameVarSizeWord();
			playerEquipment[targetSlot] = wearID;
			playerEquipmentN[targetSlot] = wearAmount;
			if (targetSlot == playerWeapon && playerEquipment[playerShield] != -1 && Item.itemTwoHanded[wearID] == true) {
				remove(playerEquipment[playerShield] , playerShield);
			}
			if (targetSlot == playerWeapon) {
				SendWeapon(wearID, GetItemName(wearID));
				playerSE = 0x328;
				playerSEW = 0x333;
				playerSER = 0x338;
				playerSEA = 0x326;
				if (Item.itemTwoHanded[wearID] == true) {
					playerSE = 0x811;
					playerSEW = 0x67F;
					playerSER = 0x680;
				}
				if (wearID == 4747) { //Torag Hammers
					playerSEA = 0x814;
				}
				pEmote = playerSE;
			}
			ResetBonus();
			GetBonus();
			WriteBonus();
			updateRequired = true;
			appearanceUpdateRequired = true;
			return true;
		}
		return false;
	}

	public int itemType(int item) {
		for (int i = 0; i < Item.capes.length; i++) {
			if(item == Item.capes[i]) {
				return playerCape;
			}
		}
		for (int i = 0; i < Item.hats.length; i++) {
			if(item == Item.hats[i]) {
				return playerHat;
			}
		}
		for (int i = 0; i < Item.boots.length; i++) {
			if(item == Item.boots[i]) {
				return playerFeet;
			}
		}
		for (int i = 0; i < Item.gloves.length; i++) {
			if(item == Item.gloves[i]) {
				return playerHands;
			}
		}
		for (int i = 0; i < Item.shields.length; i++) {
			if(item == Item.shields[i]) {
				return playerShield;
			}
		}
		for (int i = 0; i < Item.amulets.length; i++) {
			if(item == Item.amulets[i]) {
				return playerAmulet;
			}
		}
		for (int i = 0; i < Item.arrows.length; i++) {
			if(item == Item.arrows[i]) {
				return playerArrows;
			}
		}
		for (int i = 0; i < Item.rings.length; i++) {
			if(item == Item.rings[i]) {
				return playerRing;
			}
		}
		for (int i = 0; i < Item.body.length; i++) {
			if(item == Item.body[i]) {
				return playerChest;
			}
		}
		for (int i = 0; i < Item.legs.length; i++) {
			if(item == Item.legs[i]) {
				return playerLegs;
			}
		}

		//Default
		return playerWeapon;
	}

	public void remove(int wearID, int slot) {
		if(addItem(playerEquipment[slot], playerEquipmentN[slot])) {
			playerEquipment[slot] = -1;
			playerEquipmentN[slot] = 0;
			outStream.createFrame(34);
			outStream.writeWord(6);
			outStream.writeWord(1688);
			outStream.writeByte(slot);
			outStream.writeWord(0);
			outStream.writeByte(0);
			ResetBonus();
			GetBonus();
			WriteBonus();
			if (slot == playerWeapon) {
				SendWeapon(-1, "Unarmed");
			}
			updateRequired = true; appearanceUpdateRequired = true;
		}
	}

	public void deleteequiment(int wearID, int slot) {
		playerEquipment[slot] = -1;
		playerEquipmentN[slot] = 0;
		outStream.createFrame(34);
		outStream.writeWord(6);
		outStream.writeWord(1688);
		outStream.writeByte(slot);
		outStream.writeWord(0);
		outStream.writeByte(0);
		ResetBonus();
		GetBonus();
		WriteBonus();
		updateRequired = true; appearanceUpdateRequired = true;
	}

	public void setChatOptions(int publicChat, int privateChat, int tradeBlock) {
		outStream.createFrame(206);
		outStream.writeByte(publicChat);	// On = 0, Friends = 1, Off = 2, Hide = 3
		outStream.writeByte(privateChat);	// On = 0, Friends = 1, Off = 2
		outStream.writeByte(tradeBlock);	// On = 0, Friends = 1, Off = 2
	}

	public void setClientConfig(int id, int state) {
		outStream.createFrame(36);
		outStream.writeWordBigEndian(id);
		outStream.writeByte(state);
	}

	public int GetLastLogin(int Date) {
		Calendar cal = new GregorianCalendar();
		int day = cal.get(Calendar.DAY_OF_MONTH);
		int month = cal.get(Calendar.MONTH);
		int year = cal.get(Calendar.YEAR);
		int calc = ((year * 10000) + (month * 100) + day);
		return (calc - Date);
	}

	// upon connection of a new client all the info has to be sent to client prior to starting the regular communication
	public void initialize() {
		// first packet sent 
		outStream.createFrame(249);
		outStream.writeByteA(playerIsMember);		// 1 for members, zero for free
		outStream.writeWordBigEndianA(playerId);
		
		// here is the place for seting up the UI, stats, etc...
		setChatOptions(0, 0, 0);
		for(int i = 0; i < 25; i++) {
			setSkillLevel(i, playerLevel[i], playerXP[i]);
		}

		outStream.createFrame(107);

		setSidebarInterface(0, 2423); //attack tab
		setSidebarInterface(1, 3917); //skills tab
		setSidebarInterface(2, 638); //quest tab
		setSidebarInterface(3, 3213); //backpack tab
		setSidebarInterface(4, 1644); //items wearing tab
		setSidebarInterface(5, 5608); //pray tab
		setSidebarInterface(6, 1151); //magic tab
		setSidebarInterface(8, 5065); //friend
		setSidebarInterface(9, 5715); //ignore
		setSidebarInterface(10, 2449); //logout tab
		setSidebarInterface(11, 4445); //wrench tab
		setSidebarInterface(12, 147); //run tab
		setSidebarInterface(13, 6299); //harp tab

		// add player commands...
		outStream.createFrameVarSize(104);
		outStream.writeByteC(1);		// command slot
		outStream.writeByteA(0);		// 0 or 1; 1 if command should be placed on top in context menu
		outStream.writeString("Trade with");
		outStream.endFrameVarSize();

		outStream.createFrameVarSize(104);
		outStream.writeByteC(2);		// command slot
		outStream.writeByteA(0);		// 0 or 1; 1 if command should be placed on top in context menu
		outStream.writeString("Follow");
		outStream.endFrameVarSize();

		playerLastConnect = connectedFrom;

		sendMessage("Welcome to ReenScape.");
		if(playerRights >= 2 && playerRights <= 3){
			sendMessage("This provided account is for development and customer support only.");
			sendMessage("If you wish to train and play the game, please make another account for that.");
			sendMessage("But the two must NEVER interract with eachother or both accounts will be banned.");
		}
		
		if(ShowCharacterDesign) showInterface(3559);

		WriteEnergy();
		sendFrame126("ReenScape, always use the", 2451);
		sendFrame126("Bank of ReenScape", 14923);
		SendWeapon(-1, "Unarmed");

		handler.updatePlayer(this, outStream);
		handler.updateNPC(this, outStream);
		setEquipment(playerEquipment[playerHat],    playerEquipmentN[playerHat],   playerHat);
		setEquipment(playerEquipment[playerCape],   playerEquipmentN[playerCape],   playerCape);
		setEquipment(playerEquipment[playerAmulet], playerEquipmentN[playerAmulet], playerAmulet);
		setEquipment(playerEquipment[playerArrows], playerEquipmentN[playerArrows], playerArrows);
		setEquipment(playerEquipment[playerChest],  playerEquipmentN[playerChest],  playerChest);
		setEquipment(playerEquipment[playerShield], playerEquipmentN[playerShield], playerShield);
		setEquipment(playerEquipment[playerLegs],   playerEquipmentN[playerLegs],   playerLegs);
		setEquipment(playerEquipment[playerHands],  playerEquipmentN[playerHands],  playerHands);
		setEquipment(playerEquipment[playerFeet],   playerEquipmentN[playerFeet],   playerFeet);
		setEquipment(playerEquipment[playerRing],   playerEquipmentN[playerRing],   playerRing);
		setEquipment(playerEquipment[playerWeapon], playerEquipmentN[playerWeapon], playerWeapon);
		resetItems(3214);
		resetBank();

		ResetBonus();
		GetBonus();
		WriteBonus();

      pmstatus(2);
		for(int i1 = 0; i1 < handler.maxPlayers; i1++)
        if(!(handler.players[i1] == null) && handler.players[i1].isActive)
          handler.players[i1].pmupdate(playerId, 1);
		boolean pmloaded = false;
		for(int i = 0; i < friends.length; i++) {
			if(friends[i] != 0) {
				for(int i2 = 1; i2 < handler.maxPlayers; i2++) {
					if(handler.players[i2] != null && handler.players[i2].isActive && Library.mutil.playerNameToInt64(handler.players[i2].playerName) == friends[i]) {
						if(playerRights >= 2 || handler.players[i2].configPrivateChat == 0 ||(handler.players[i2].configPrivateChat == 1 && handler.players[i2].isinpm(Library.mutil.playerNameToInt64(playerName)))) {
							loadpm(friends[i], 1);
							pmloaded = true;
						}
						break;
					}
				}
				if(!pmloaded) 	loadpm(friends[i], 0);
				pmloaded = false;
			}
			for(int i1 = 1; i1 < handler.maxPlayers; i1++) {
				if(handler.players[i1] != null && handler.players[i1].isActive == true) {
					handler.players[i1].pmupdate(playerId, 1);
				}
			}
		}

		//Objects
		for (int i = 0; i < Server.objectUpdater.MaxObjects; i++) {
			if (Server.objectUpdater.ObjectID[i] > -1) {
				if (Server.objectUpdater.ObjectOpen[i] != Server.objectUpdater.ObjectOriOpen[i]) {
					ChangeDoor(i);
				}
			}
		}
	}

	public void update() {
		handler.updatePlayer(this, outStream);
		handler.updateNPC(this, outStream);
		flushOutStream();
	}

	public static final int packetSizes[] = {
		0, 0, 0, 1, -1, 0, 0, 0, 0, 0, //0
		0, 0, 0, 0, 8, 0, 6, 2, 2, 0,  //10
		0, 2, 0, 6, 0, 12, 0, 0, 0, 0, //20
		0, 0, 0, 0, 0, 8, 4, 0, 0, 2,  //30
		2, 6, 0, 6, 0, -1, 0, 0, 0, 0, //40
		0, 0, 0, 12, 0, 0, 0, 0, 8, 0, //50
		0, 8, 0, 0, 0, 0, 0, 0, 0, 0,  //60
		6, 0, 2, 2, 8, 6, 0, -1, 0, 6, //70
		0, 0, 0, 0, 0, 1, 4, 6, 0, 0,  //80
		0, 0, 0, 0, 0, 3, 0, 0, -1, 0, //90
		0, 13, 0, -1, 0, 0, 0, 0, 0, 0,//100
		0, 0, 0, 0, 0, 0, 0, 6, 0, 0,  //110
		1, 0, 6, 0, 0, 0, -1, 0, 2, 6, //120
		0, 4, 6, 8, 0, 6, 0, 0, 0, 2,  //130
		0, 0, 0, 0, 0, 6, 0, 0, 0, 0,  //140
		0, 0, 1, 2, 0, 2, 6, 0, 0, 0,  //150
		0, 0, 0, 0, -1, -1, 0, 0, 0, 0,//160
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //170
		0, 8, 0, 3, 0, 2, 0, 0, 8, 1,  //180
		0, 0, 12, 0, 0, 0, 0, 0, 0, 0, //190
		2, 0, 0, 0, 0, 0, 0, 0, 4, 0,  //200
		4, 0, 0, 0, 7, 8, 0, 0, 10, 0, //210
		0, 0, 0, 0, 0, 0, -1, 0, 6, 0, //220
		1, 0, 0, 0, 6, 0, 6, 8, 1, 0,  //230
		0, 4, 0, 0, 0, 0, -1, 0, -1, 4,//240
		0, 0, 6, 6, 0, 0, 0            //250
	};
	public int SaveTimer = 240;
	public int packetSize = 0, packetType = -1;
	
	public boolean process() {		// is being called regularily every 500ms
		if (actionAmount < 0) {
			actionAmount = 0;
		}
		if (actionTimer > 0) {
			actionTimer -= 1;
		}
		if (actionAmount > 4) {
			sendMessage("Kicked for acting too fast!");
			Library.print.println("Client acts too fast - disconnected!");
			disconnected = true;
		}
		
		LogoutTimer -= 1;
		StunnedTimer -= 1;
		//Delay -= 1;
		AddObjectFire();
		
		updateRequired = true;
        appearanceUpdateRequired = true;
		
		if(Delay > 0) Delay -= 1;

		if(FWGoalX > -1 && FWGoalY > -1){
			if((currentX == FWGoalX) && (currentY == FWGoalY)){
			ForceWalk = false;
			FWGoalX = -1;
			FWGoalY = -1;
			resetWalkingQueue();
			}
		}
		
		if(FollowingID > 0){
			Follow.UpdateFollow(this, (PacketParser) ClientUpdater.players[FollowingID]);
		}
		
		if (pickingUp == true) {
			if (absX == pickupX && absY == pickupY) {
				try {
					if(ItemUpdater.itemExists(pickupID, absX, absY)) {
						pickUpItem(pickupID, pickupAmt);
						ItemUpdater.removeItem(pickupID, pickupX, pickupY, pickupAmt);
						removeGroundItem(pickupX, pickupY, pickupID);
						resetItems(3214); 
						resetPickup();
					}
				}
				catch (Exception e) {}
			}
		}
		
		//GameTime
		playerGameCount++;
		if (playerGameCount == 120000) { //evry minute
			playerGameTime++;
			playerGameCount = 0;
		}
		if ((playerGameTime % 1440) == 0) { //1440 minutes = 24 hours
			for (int i = 0; i < bankItems.length; i++) {
				if (bankItems[i] == 995) {
					bankItemsN[i] += ((bankItemsN[i] / 100) * 4); //increase money like in real banks (4% rente)
				}
			}
		}
		//Shop
		if (UpdateShop == true) {
			resetItems(3823);
			resetShop(MyShopID);
		}
		//Fishing
		if(fishing[0] > 0) {
			fishing[3]--;
			if(fishing[3] == 0) {
				Skill.fishing.action(this, 1);
			} else {
				Animation(fishing[2]);
			}
		}
		//Smithing
		if(smithing[3] >= 1) {
			smithing[4]--;
			if(smithing[4] == 0) {
				smithing[4] = 2;
				smithing[3]--;
				Skill.smithing.makeItems(this);
				if(smithing[3] == 0) {
					smithing[0] = 0;
					smithing[1] = 0;
					smithing[2] = 0;
					smithing[3] = 0;
					smithing[4] = 0;
				}
			}
		}
		//Smelting
		if(smelting[1] >= 1) {
			smelting[0]--;
			if(smelting[0] == 0) {
				Skill.smithing.makeItems2(this, smelting[2]);
				smelting[1]--;
				smelting[0] = 4;
				if(smelting[1] == 0) {
					smelting[0] = 0;
					smelting[1] = 0;
					smelting[2] = 0;
				}
			}
		}
		//Energy
		if (playerEnergy < 100) {
			if (playerEnergyGian >= Server.EnergyRegian) {
				playerEnergy += 1;
				playerEnergyGian = 0;
			}
			playerEnergyGian++;
			if (playerEnergy >= 0) {
				WriteEnergy();
			}
		}
		//Trade Check
		if (tradeRequest > 0) {
			sendMessage(ClientUpdater.players[tradeRequest].playerName+":tradereq:");
			tradeRequest = 0;
		}
		if (tradeOtherDeclined == true) {
			if (ClientUpdater.players[tradeWith] != null) {
				sendMessage(ClientUpdater.players[tradeWith].playerName+" declined the trade.");
			} else {
				sendMessage("Other player declined the trade.");
			}
			RemoveAllWindows();
			DeclineTrade();
			tradeOtherDeclined = false;
		}
		if (tradeWaitingTime > 0) {
			tradeWaitingTime--;
			if (tradeWaitingTime <= 0) {
				resetTrade();
			}
		}
		if (AntiTradeScam == true) {
			sendFrame126("", 3431);
			AntiTradeScam = false;
		}
		if (tradeWith > 0) {
			if (ClientUpdater.players[tradeWith] != null) {
				if (tradeStatus == 5) {
					if (ClientUpdater.players[tradeWith].TradeConfirmed == true) {
						ClientUpdater.players[tradeWith].tradeStatus = 5;
					}
					resetTrade();
				} else {
					int OtherStatus = ClientUpdater.players[tradeWith].tradeStatus;
					if (OtherStatus == 1) {
						ClientUpdater.players[tradeWith].tradeStatus = 2;
						tradeStatus = 2;
						AcceptTrade();
						ClientUpdater.players[tradeWith].tradeWaitingTime = 0;
						tradeWaitingTime = 0;
					} else if (OtherStatus == 3) {
						if (tradeStatus == 2) {
							sendFrame126("Other player has accepted.", 3431);				
						} else if (tradeStatus == 3) {
							TradeGoConfirm();
						}
					} else if (OtherStatus == 4) {
						if (tradeStatus == 3) {
							sendFrame126("Other player has accepted.", 3535);				
						} else if (tradeStatus == 4) {
							ConfirmTrade();
							if (ClientUpdater.players[tradeWith].TradeConfirmed == true) {
								ClientUpdater.players[tradeWith].tradeStatus = 5;
							}
						}
					}
					if (tradeUpdateOther == true) {
						resetOTItems(3416);
						tradeUpdateOther = false;
					}
				}
			} else {
				resetTrade();
			}
		}
		if (WanneTrade == 1) {
			if (WanneTradeWith > ClientUpdater.maxPlayers) {
				resetTrade();
			} else if (ClientUpdater.players[WanneTradeWith] != null) {
				if (GoodDistance2(absX, absY, ClientUpdater.players[WanneTradeWith].absX, ClientUpdater.players[WanneTradeWith].absY ,1) == true) {
					int tt1 = ClientUpdater.players[WanneTradeWith].tradeStatus;
					int tt2 = tradeStatus;
					if (tt1 <= 0 && tt2 <= 0 && ClientUpdater.players[WanneTradeWith].tradeWaitingTime == 0) {
						tradeWith = WanneTradeWith;
						tradeWaitingTime = 40;
						ClientUpdater.players[tradeWith].tradeRequest = playerId;
						sendMessage("Sending trade offer...");
					} else if (tt1 <= 0 && tt2 <= 0 && ClientUpdater.players[WanneTradeWith].tradeWaitingTime > 0) {
						tradeWith = WanneTradeWith;
						tradeStatus = 1;
						AcceptTrade();
					}
					WanneTrade = 0;
					WanneTradeWith = 0;
				}
			} else {
				resetTrade();
			}
		} else if (WanneTrade == 2) {
			if (WanneTradeWith > ClientUpdater.maxPlayers) {
				resetTrade();
			} else if (ClientUpdater.players[WanneTradeWith] != null) {
				if (GoodDistance2(absX, absY, ClientUpdater.players[WanneTradeWith].absX, ClientUpdater.players[WanneTradeWith].absY ,1) == true) {
					if (ClientUpdater.players[WanneTradeWith].tradeWith == playerId && ClientUpdater.players[WanneTradeWith].tradeWaitingTime > 0) {
						tradeWith = WanneTradeWith;
						tradeStatus = 1;
						AcceptTrade();
					} else {
						tradeWith = WanneTradeWith;
						tradeWaitingTime = 40;
						ClientUpdater.players[tradeWith].tradeRequest = playerId;
						sendMessage("Sending trade offer...");
					}
					WanneTrade = 0;
					WanneTradeWith = 0;
				}
			} else {
				resetTrade();
			}
		}
		//wilderness check
		if (IsInWilderness(absX, absY, 1) == true && IsInWilderness == false) {
			outStream.createFrameVarSize(104);
			outStream.writeByteC(3);		// command slot (does it matter which one?)
			outStream.writeByteA(1);		// 0 or 1; 1 if command should be placed on top in context menu
			outStream.writeString("Attack");
			outStream.endFrameVarSize();
			IsInWilderness = true;
		} else if (IsInWilderness(absX, absY, 1) == false && IsInWilderness == true) {
			IsInWilderness = false;
			outStream.createFrameVarSize(104);
			outStream.writeByteC(3);		// command slot (does it matter which one?)
			outStream.writeByteA(1);		// 0 or 1; 1 if command should be placed on top in context menu
			outStream.writeString("Attack");
			outStream.endFrameVarSize();
		}
		if (IsInWilderness(absX, absY, 2) == false && WildernessWarning == true) {
			WildernessWarning = false;
		} else if (IsInWilderness(absX, absY, 2) == true && WildernessWarning == false) {
			sendFrame248(1908, 3213);
			WildernessWarning = true;
		}
		//check stairs
		if (stairs > 0) {
			if (GoodDistance(skillX, skillY, absX, absY, stairDistance) == true) {
				stairs(stairs, absX, absY);
			}
		}
		//objects
		if (doors > -1) {
			if (GoodDistance2(skillX, skillY, absX, absY, 1) == true) {
				ChangeDoor(doors);
				doors = -1;
			}
		}
		//check banking
		if (WanneBank > 0) {
			if (GoodDistance(skillX, skillY, absX, absY, WanneBank) == true) {
				openUpBank();
				WanneBank = 0;
			}
		}
		//check shopping
		if (WanneShop > 0) {
			if (GoodDistance(skillX, skillY, absX, absY, 1) == true) {
				openUpShop(WanneShop);
				WanneShop = 0;
			}
		}
		//Pick Up Item Check
        if(WannePickUp == true && IsUsingSkill == false) {
          if(pickUpItem(PickUpID, PickUpAmount) == true) {
            PickUpID = 0;
            PickUpAmount = 0;
            PickUpDelete = 0;
            WannePickUp = false;
          }
        }
		//Attacking in wilderness
		if (IsAttacking == true && IsDead == false) {
			if (ClientUpdater.players[AttackingOn] != null) {
				if (ClientUpdater.players[AttackingOn].IsDead == false) {
					Attack();
				} else {
					ResetAttack();
				}
			} else {
				ResetAttack();
			}
		}
		if(MeleeNpcSlot > 0){
			if(Delay == -1) Delay = 8;
			Skill.melee.NPC(MeleeNpcSlot, this);
		}
		if(MeleePlayerSlot > 0){
			Skill.melee.Player(MeleePlayerSlot, this);
		}
		//check if ring of life ie equiped etc...
		if (playerEquipment[playerRing] == 2570 && playerLevel[playerHitpoints] <= (int)((double)((double)getLevelForXP(playerXP[3]) / 10.0) + 0.5)) {
			SafeMyLife = true;
		}
		//if ring of life is activated
		if (SafeMyLife == true) {
			ApplyRingOfLife();
		}
		//If killed apply dead
		if (IsDead == true) {
			ApplyDead();
		}
		//update correct hp in stat screen
		if (NewHP < 100) {
			playerLevel[playerHitpoints] = NewHP;
			setSkillLevel(playerHitpoints, NewHP, playerXP[playerHitpoints]);
			NewHP = 100;
		}
		//Snowing
		if (IsSnowing == 1) {
			outStream.createFrame(208);
			outStream.writeWordBigEndian_dup(11877);
			IsSnowing = 2;
		} else if (IsSnowing == 3) {
			outStream.createFrame(208);
			outStream.writeWordBigEndian_dup(65535);
			IsSnowing = 0;
		}
		//Npc Talking
		if (NpcWanneTalk == 2) { //Bank Booth
			if (GoodDistance2(absX, absY, skillX, skillY, 1) == true) {
				NpcDialogue = 1;
				NpcTalkTo = GetNPCID(skillX, (skillY - 1));
				NpcWanneTalk = 0;
			}
		} else if (NpcWanneTalk > 0) {
			if (GoodDistance2(absX, absY, skillX, skillY, 2) == true) {
				NpcDialogue = NpcWanneTalk;
				NpcTalkTo = GetNPCID(skillX, skillY);
				NpcWanneTalk = 0;
			}
		}
		if (NpcDialogue > 0 && NpcDialogueSend == false) {
			UpdateNPCChat();
		}

		if (isKicked) { disconnected = true; outStream.createFrame(109); };
		
		if (globalMessage.length() > 0) {
			sendMessage(globalMessage);
			globalMessage = "";
		}
		if(disconnected) return false;
		try {
			if(timeOutCounter++ > 20) {
				Library.print.println("Client lost connection: timeout");
				disconnected = true;
				return false;
			}
			if(in == null) return false;

			int avail = in.available();
			if(avail == 0) return false;

			if(packetType == -1) {
				packetType = in.read() & 0xff;
				if(inStreamDecryption != null)
					packetType = packetType - inStreamDecryption.getNextKey() & 0xff;
				packetSize = packetSizes[packetType];
				avail--;
            		}
			if(packetSize == -1) {
				if(avail > 0) {
					// this is a variable size packet, the next byte containing the length of said
					packetSize = in.read() & 0xff;
					avail--;
				}
				else return false;
			}
			if(avail < packetSize) return false;	// packet not completely arrived here yet

			fillInStream(packetSize);
            		timeOutCounter = 0;			// reset

			parseIncomingPackets();		// method that does actually interprete these packets

			packetType = -1;
		} catch(java.lang.Exception __ex) {
			Print.error("Unexpected error occured whilst parsing packets.","PacketParser","process", __ex);
			disconnected = true;
		}
		return true;
	}

	public void parseIncomingPackets(){
		int i;
		int junk;
		int junk2;
		int junk3;
		switch(packetType) {
		/*317*/
		
			//NPC
			case 155:	PacketUpdater.npc.FirstClick(this); break;
			case 17:	PacketUpdater.npc.SecondClick(this); break;
			case 21:	PacketUpdater.npc.ThirdClick(this); break;
			case 40:	PacketUpdater.npc.ChatAdvance(this); break;
			
			//OBJECT
			case 132:	PacketUpdater.obj.FirstClick(this); break;
			case 252:	PacketUpdater.obj.SecondClick(this); break;
			case 70:	PacketUpdater.obj.ThirdClick(this); break;
			
			//ITEM
			case 41:	PacketUpdater.item.Wield(this); break;
			case 214:	PacketUpdater.item.MoveSlot(this); break;
			case 53:	PacketUpdater.itemOnOther.ItemOnItem(this); break;
			case 192:	PacketUpdater.itemOnOther.ItemOnObject(this); break;
			case 14:	PacketUpdater.itemOnOther.ItemOnPlayer(this); break;
			case 122:	PacketUpdater.item.FirstClick(this); break;	
			case 87:	PacketUpdater.item.DropOnFloor(this); break;
			case 236:	PacketUpdater.item.PickupFromFloor(this); break;
			
			//SKILL
			case 72:	PacketUpdater.npc.Attack(this); break;	
			case 73:	PacketUpdater.player.Attack(this); break;
			case 131:	PacketUpdater.npc.Spell(this); break;
			
			//PLAYER
			case 128:	PacketUpdater.player.TradeRequest(this); break;
			case 139:	PacketUpdater.player.TradeAnswer(this); break;
			case 95:	PacketUpdater.player.UpdateSettings(this); break;
			case 103:	PacketUpdater.player.Command(this); break;
			case 153:	PacketUpdater.player.Follow(this); break;
			case 188:	PacketUpdater.player.AddFriend(this); break;
			case 215:	PacketUpdater.player.RemoveFriend(this); break;
			case 133:	PacketUpdater.player.AddIgnore(this); break;
			case 74:	PacketUpdater.player.RemoveIgnore(this); break;
			case 126:	PacketUpdater.player.PM(this); break;
			
			//OTHER
			case 145:	PacketUpdater.other.RemoveOne(this); break;
			case 117:	PacketUpdater.other.RemoveFive(this); break;
			case 43:	PacketUpdater.other.RemoveTen(this); break;
			case 129:	PacketUpdater.other.RemoveAll(this); break;
			case 135:	PacketUpdater.other.RemoveX(this); break;
			case 208:	PacketUpdater.other.PutX(this); break;
			case 4:		PacketUpdater.other.PublicChat(this); break;
			case 130:	PacketUpdater.other.CloseInterface(this); break;
			case 210:	/*ENTERING NEW REGION*/ break;
			case 121:	/*LOADING OBJECTS IN NEW AREA*/ break;
			case 253:	PacketUpdater.other.BurnFire(this); break;
			case 185:	PacketUpdater.button.ActionButton(this); break;
			case 101:	PacketUpdater.other.CharacterDesign(this); break;
			case 3:		PacketUpdater.player.Focus(this); break;
			case 86:	/*CAMERA ANGLE*/ break;
			case 241:	/*MOUSE CLICKS*/ break;
			
			//IDLE
			case 0:		/*COUNTER*/ break;
			case 202:	logout();  break;
			
			/*BEGIN Anti-bot packets*/
			case 226:			case 78:			case 148:
			case 183:			case 230:			case 136:
			case 189:			case 152:			case 200:
			case 85:			case 165:			case 238:
			case 150:			case 36:			case 246:
			case 77:
			break;
			/*END Anti-bot packets*/

			//Walking
			case 248:
				packetSize -= 14;		// ignore the junk
			case 164:	// regular walk
			case 98:	// walk on command
				MeleeNpcSlot = 0;
				MeleePlayerSlot = 0;
				Delay = -1;
				Skill.fishing.stop(this);
				if(StunnedTimer > 0){
					sendMessage("You are stunned!");
				}
				else if (IsDead == false && ForceWalk == false) {
					faceNPC(65535);
					FollowingID = -1;
					newWalkCmdSteps = packetSize - 5;
					if(newWalkCmdSteps % 2 != 0)
						println_debug("Warning: walkTo("+packetType+") command malformed: "+Library.mutil.Hex(inStream.buffer, 0, packetSize));
						newWalkCmdSteps /= 2;
					if(++newWalkCmdSteps > walkingQueueSize) {
						println_debug("Warning: walkTo("+packetType+") command contains too many steps ("+newWalkCmdSteps+").");
						newWalkCmdSteps = 0;
						break;
					}
					int firstStepX = inStream.readSignedWordBigEndianA();
					int tmpFSX = firstStepX;
					firstStepX -= mapRegionX * 8;
					for(i = 1; i < newWalkCmdSteps; i++) {
						newWalkCmdX[i] = inStream.readSignedByte();
						newWalkCmdY[i] = inStream.readSignedByte();
						tmpNWCX[i] = newWalkCmdX[i];
						tmpNWCY[i] = newWalkCmdY[i];
					}
					newWalkCmdX[0] = newWalkCmdY[0] = tmpNWCX[0] = tmpNWCY[0] = 0;
					int firstStepY = inStream.readSignedWordBigEndian();
					int tmpFSY = firstStepY;
					firstStepY -= mapRegionY * 8;
					newWalkCmdIsRunning = inStream.readSignedByteC() == 1;
					for(i = 0; i < newWalkCmdSteps; i++) {
						newWalkCmdX[i] += firstStepX;
						newWalkCmdY[i] += firstStepY;
					}
					poimiY = firstStepY;
					poimiX = firstStepX;

					//stairs check
					if (stairs > 0) {
						resetStairs();
					}
					//pick up item check
					if (WannePickUp == true) {
						PickUpID = 0;
						PickUpAmount = 0;
						PickUpDelete = 0;
						WannePickUp = false;
					}
					//attack check
					if (IsAttacking == true) {
						ResetAttack();
					}
					//attack NPC check
					if (IsAttackingNPC == true) {
						ResetAttackNPC();
					}
					//Npc Talking
					if (NpcDialogue > 0) {
						NpcDialogue = 0;
						NpcTalkTo = 0;
						NpcDialogueSend = false;
						RemoveAllWindows();
					}
					//banking
					if (IsBanking == true) {
						RemoveAllWindows();
					}
					//shopping
					if (IsShopping == true) {
						IsShopping = false;
						MyShopID = 0;
						UpdateShop = false;
						RemoveAllWindows();
					}
					//trading
					if (tradeStatus >= 2) {
						ClientUpdater.players[tradeWith].tradeOtherDeclined = true;
						DeclineTrade();
						sendMessage("You decline the trade.");
						RemoveAllWindows();
					}
				}
				break;

			default:
				int actionButtonId1 = Library.mutil.HexToInt(inStream.buffer, 0, packetSize);
				println_debug("Unhandled packet ["+packetType+", size="+packetSize+"]: ]"+Library.mutil.Hex(inStream.buffer, 1, packetSize)+"[");
				println_debug("Action Button: "+actionButtonId1);
			break;
		}
	}
	private int somejunk;

	public boolean ResetPlayerVars() {
		teleportToX = 0;
		teleportToY = 0;
		heightLevel = 0;
		playerRights = 0;
		playerIsMember = 1;
		playerMessages = 0;
		playerLastConnect = "";
		playerLastLogin = 20050101;
		playerEnergy = 0;
		playerEnergyGian = 0;
		playerFollowID = -1;
		playerGameTime = 0;
		playerGameCount = 0;
		for (int i = 0; i < playerItems.length; i++) {
			playerItems[i] = 0;
			playerItemsN[i] = 0;
		}
		for (int i = 0; i < playerEquipment.length; i++) {
			playerEquipment[i] = -1;
			playerEquipmentN[i] = 0;
		}
		for (int i = 0; i < bankItems.length; i++) {
			bankItems[i] = 0;
			bankItemsN[i] = 0;
		}
		for (int i = 0; i < playerLevel.length; i++) {
			if (i == playerHitpoints) {
				playerLevel[i] = 10;
				playerXP[i] = 1055;
			} else {
				playerLevel[i] = 1;
				playerXP[i] = 0;
			}
		}
		for (int i = 0; i < friends.length; i++) {
			friends[i] = 0;
		}
		for (int i = 0; i < ignores.length; i++) {
			ignores[i] = 0;
		}
		for (int i = 0; i < playerLook.length; i++) {
			playerLook[i] = -1;
		}
		for (int i = 0; i < playerFollow.length; i++) {
			playerFollow[i] = -1;
		}
		for (int i = 0; i < Server.objectUpdater.MaxObjects; i++) {
			ChangeDoor[i] = false;
		}
		resetTrade(); //no trading, so reset the trade vars
		return true;
	}
	
					public void UnWield(int Slot, int ID){
						if(playerEquipment[Slot] > 0) {
							remove(ID , Slot);
						}
					}

	public int EssenceMineX[] = {2893,2921,2911,2926,2899};
	public int EssenceMineY[] = {4846,4846,4832,4817,4817};
/*
[0] North West
[1] North East
[2] Center
[3] South East
[4] South West
*/
	public int EssenceMineRX[] = {3253,3105,2681,2591};
	public int EssenceMineRY[] = {3401,9571,3325,3086};
/*
[0] Varrock
[1] Wizard Tower
[2] Ardougne
[3] Magic Guild
*/
	public boolean stairs(int stairs, int teleX, int teleY) {
		if (IsStair == false) {
			IsStair = true;
			if (stairs == 1) {
				heightLevel += 1;
			} else if (stairs == 2) {
				heightLevel -= 1;
			} else if (stairs == 21) {
				heightLevel += 1;
			} else if (stairs == 22) {
				heightLevel -= 1;
			}
			teleportToX = teleX;
			teleportToY = teleY;
			if (stairs == 3 || stairs == 5 || stairs == 9) {
				teleportToY += 6400;
			} else if (stairs == 4 || stairs == 6 || stairs == 10) {
				teleportToY -= 6400;
			} else if (stairs == 7) {
				teleportToX = 3104;
				teleportToY = 9576;
			} else if (stairs == 8) {
				teleportToX = 3105;
				teleportToY = 3162;
			} else if (stairs == 11) {
				teleportToX = 2856;
				teleportToY = 9570;
			} else if (stairs == 12) {
				teleportToX = 2857;
				teleportToY = 3167;
			} else if (stairs == 13) {
				heightLevel += 3;
				teleportToX = skillX;
				teleportToY = skillY;
			} else if (stairs == 15) {
				teleportToY += (6400 - (stairDistance + stairDistanceAdd));
			} else if (stairs == 14) {
				teleportToY -= (6400 - (stairDistance + stairDistanceAdd));
			} else if (stairs == 16) {
				teleportToX = 2828;
				teleportToY = 9772;
			} else if (stairs == 17) {
				teleportToX = 3494;
				teleportToY = 3465;
			} else if (stairs == 18) {
				teleportToX = 3477;
				teleportToY = 9845;
			} else if (stairs == 19) {
				teleportToX = 3543;
				teleportToY = 3463;
			} else if (stairs == 20) {
				teleportToX = 3549;
				teleportToY = 9865;
			} else if (stairs == 21) {
				teleportToY += (stairDistance + stairDistanceAdd);
			} else if (stairs == 22) {
				teleportToY -= (stairDistance + stairDistanceAdd);
			} else if (stairs == 23) {
				teleportToX = 2480;
				teleportToY = 5175;
			} else if (stairs == 24) {
				teleportToX = 2862;
				teleportToY = 9572;
			} else if (stairs == 25) {
				Essence = (heightLevel / 4);
				heightLevel = 0;
				teleportToX = EssenceMineRX[Essence];
				teleportToY = EssenceMineRY[Essence];
			} else if (stairs == 26) {
				int EssenceRnd = Library.mutil.random3(EssenceMineX.length);
				teleportToX = EssenceMineX[EssenceRnd];
				teleportToY = EssenceMineY[EssenceRnd];
				heightLevel = (Essence * 4);
			} else if (stairs == 27) {
				teleportToX = 2453;
				teleportToY = 4468;
			} else if (stairs == 28) {
				teleportToX = 3201;
				teleportToY = 3169;
			}
			if (stairs == 5 || stairs == 10) {
				teleportToX += (stairDistance + stairDistanceAdd);
			}
			if (stairs == 6 || stairs == 9) {
				teleportToX -= (stairDistance - stairDistanceAdd);
			}
		}
		resetStairs();
		return true;
	}
	public boolean resetStairs() {
		stairs = 0;
		skillX = -1;
		skillY = -1;
		stairDistance = 1;
		stairDistanceAdd = 0;
		IsUsingSkill = false;
		return true;
	}

	public boolean IsInWilderness(int coordX, int coordY, int Type) {
		if (Type == 1) {
			if (coordY >= 3520 && coordY <= 3967 && coordX <= 3392 && coordX >= 2942) {
				return true;
			}
		} else if (Type == 2) {
			if (coordY >= 3512 && coordY <= 3967 && coordX <= 3392 && coordX >= 2942) {
				return true;
			}
		}
		return false;
	}
	public boolean Attack() {
		int EnemyX = ClientUpdater.players[AttackingOn].absX;
		int EnemyY = ClientUpdater.players[AttackingOn].absY;
		int EnemyHP = ClientUpdater.players[AttackingOn].playerLevel[playerHitpoints];
		double EnemyHPExp = ClientUpdater.players[AttackingOn].playerXP[playerHitpoints];
		boolean RingOfLife = false;
		if (ClientUpdater.players[AttackingOn].playerEquipment[playerRing] == 2570) {
			RingOfLife = true;
		}
		int hitDiff = 0;
		hitDiff = Library.mutil.random(playerMaxHit);
		if (GoodDistance(EnemyX, EnemyY, absX, absY, 1) == true) {
		  if (actionTimer == 0) {
		    if (IsInWilderness(EnemyX, EnemyY, 1) == true) {
			if (RingOfLife == true && EnemyHP <= (int)((getLevelForXP(EnemyHPExp) / 10.0) + 0.5)) {
				ClientUpdater.players[AttackingOn].SafeMyLife = true;
			} else {
				if (ClientUpdater.players[AttackingOn].IsDead == true) {
					ResetAttack();
				} else {
					actionAmount++;
					setAnimation(playerSEA);
					ClientUpdater.players[AttackingOn].hitUpdateRequired = true;
					ClientUpdater.players[AttackingOn].updateRequired = true;
					ClientUpdater.players[AttackingOn].appearanceUpdateRequired = true;
					if ((EnemyHP - hitDiff) < 0) {
						hitDiff = EnemyHP;
					}
					ClientUpdater.players[AttackingOn].hitDiff += hitDiff;
					actionTimer = 7;
				}
			}
			return true;
		    } else {
		      sendMessage("This player is not in the Wilderness.");
		      ResetAttack();
		    }
		  }
		}
		return false;
	}
	public boolean ResetAttack() {
		IsAttacking = false;
		AttackingOn = 0;
		resetAnimation();
		IsUsingSkill = false;
		return true;
	}
	public boolean ApplyDead() {
		if (IsDeadTimer == false) {
			actionAmount++;
			actionTimer = 20;
			ResetAttack();
			ResetAttackNPC();
			setAnimation(0x900);
			sendMessage("Oh dear, you are dead!");
			IsDeadTimer = true;
		}
		if (actionTimer == 0 && IsDeadTimer == true) {
			teleportToX = 3221;
			teleportToY = 3219;
			IsDeadTeleporting = true;
			playerLevel[playerHitpoints] = getLevelForXP(playerXP[playerHitpoints]);
			setSkillLevel(playerHitpoints, playerLevel[playerHitpoints], playerXP[playerHitpoints]);
			resetAnimation();
			updateRequired = true;
			appearanceUpdateRequired = true;
		}
		return true;
	}
	public boolean ApplyRingOfLife() {
		if (IsDeadTimer == false) {
			actionAmount++;
			actionTimer = 4;
			ResetAttack();
			setAnimation(0x718);
			sendMessage("Ring of Life saved your life !");
			deleteequiment(2570, playerRing); //2570 = ring of life
			IsDeadTimer = true;
		}
		if (actionTimer == 0 && IsDeadTimer == true) {
			teleportToX = 3254;
			teleportToY = 3420;
			resetAnimation();
			IsDeadTeleporting = true;
			updateRequired = true;
			appearanceUpdateRequired = true;
		}
		return true;
	}
	public boolean IsItemInBag(int ItemID) {
		for (int i = 0; i < playerItems.length; i++) {
			if ((playerItems[i] - 1) == ItemID) {
				return true;
			}
		}
		return false;
	}
	public boolean AreXItemsInBag(int ItemID, int Amount) {
		int ItemCount = 0;
		for (int i = 0; i < playerItems.length; i++) {
			if ((playerItems[i] - 1) == ItemID) {
				ItemCount++;
			}
			if (ItemCount == Amount) {
				return true;
			}
		}
		return false;
	}
	public int GetItemSlot(int ItemID) {
		for (int i = 0; i < playerItems.length; i++) {
			if ((playerItems[i] - 1) == ItemID) {
				return i;
			}
		}
		return -1;
	}
	public int GetXItemsInBag(int ItemID) {
		int ItemCount = 0;
		for (int i = 0; i < playerItems.length; i++) {
			if ((playerItems[i] - 1) == ItemID) {
				ItemCount++;
			}
		}
		return ItemCount;
	}
	
	public boolean check(int id){
		for(int i = 0; i < playerItems.length; i++){
			if ((playerItems[i] - 1) == id) {
				return true;
			}
		}
		for(int i = 0; i < playerEquipment.length; i++){
			if((playerEquipment[i] - 1) == id){
				return true;
			}
		}
	return false;
	}
	
	public int untradable[] = {84,3006,4653,4703,744,793,6959,6070,6603,6570,6865,6866,6867,1419,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,962,963,1053,1054,1050,1051}; // put all untradable items here
  
	public boolean isUntradable(int item) {
		for(int i = 0; i < untradable.length; i++) {
			if(untradable[i] == item)
				return true;
		}
    return false;
	}
	
	public int Tradecompete = 0;
	public int Publicchat = 0;

	public void pmstatus(int status) { //status: loading = 0  connecting = 1  fine = 2 
		outStream.createFrame(221);
		outStream.writeByte(status);
	}

	public boolean isinpm(long l) {
		for(int i = 0; i < friends.length; i++) {
			if (friends[i] != 0) {
				if(l == friends[i]) {
					return true;
				}
			}
		}
		return false;
	}

	public void pmupdate(int pmid, int world) {
		long l = Library.mutil.playerNameToInt64(handler.players[pmid].playerName);
		if (handler.players[pmid].Privatechat == 0) {
			for (int i = 0; i < friends.length; i++) {
				if (friends[i] != 0) {
					if (l == friends[i]) {
						loadpm(l, world);
						return;
					}
				}
			}
		} else if(handler.players[pmid].Privatechat == 1) {
			for (int i1 = 0; i1 < friends.length; i1++) {
				if (friends[i] != 0) {
					if (l == friends[i1]) {
    			        		if(handler.players[pmid].isinpm(Library.mutil.playerNameToInt64(playerName)) && playerRights > 2) {
    			    				loadpm(l, world);
							return;
						} else {
							loadpm(l, 0);
							return;
						}
					}
				}
			}
		} else if(handler.players[pmid].Privatechat == 2) {
			for(int i2 = 0; i2 < friends.length; i2++) {
				if (friends[i] != 0) {
					if(l == friends[i2] && playerRights < 2) {
						loadpm(l, 0);
						return;
					}
				}
			}
		}
	}

	public void sendpm(long name, int rights, byte[] chatmessage, int messagesize) {
		outStream.createFrameVarSize(196);
		outStream.writeQWord(name);
		outStream.writeDWord(handler.lastchatid++);//must be different for each message
		outStream.writeByte(rights);
		outStream.writeBytes(chatmessage, messagesize , 0);
		outStream.endFrameVarSize();
	}

	public void loadpm(long name, int world) {
		if(world != 0) world += 9;
		else world += 1;
		outStream.createFrame(50);
		outStream.writeQWord(name);
		outStream.writeByte(world);
	}

	public boolean AttackNPC() {
		int EnemyX = Server.npcUpdater.npcs[attacknpc].absX;
		int EnemyY = Server.npcUpdater.npcs[attacknpc].absY;
		int EnemyHP = Server.npcUpdater.npcs[attacknpc].HP;
		int hitDiff = 0;
		hitDiff = Library.mutil.random(playerMaxHit);
		if (GoodDistance(EnemyX, EnemyY, absX, absY, 1) == true) {
			if (actionTimer == 0) {
				if (Server.npcUpdater.npcs[attacknpc].IsDead == true) {
					ResetAttackNPC();
				} else {
					actionAmount++;
					setAnimation(playerSEA);
					if ((EnemyHP - hitDiff) < 0) {
						hitDiff = EnemyHP;
					}
					Server.npcUpdater.npcs[attacknpc].hitDiff += hitDiff;
					Server.npcUpdater.npcs[attacknpc].Killing[playerId] += hitDiff;
					Server.npcUpdater.npcs[attacknpc].updateRequired = true;
					Server.npcUpdater.npcs[attacknpc].hitUpdateRequired = true;
					double TotalExp = 0;
					if (FightType != 3) {
						TotalExp = (double)(4 * hitDiff);
						TotalExp = (double)(TotalExp * CombatExpRate);
						addSkillXP((int)(TotalExp), SkillID);
					} else {
						TotalExp = (double)(1.33 * hitDiff);
						TotalExp = (double)(TotalExp * CombatExpRate);
						addSkillXP((int)(TotalExp), playerAttack);
						addSkillXP((int)(TotalExp), playerDefence);
						addSkillXP((int)(TotalExp), playerStrength);
					}
					TotalExp = (double)(1.33 * hitDiff);
					TotalExp = (double)(TotalExp * CombatExpRate);
					addSkillXP((int)(TotalExp), playerHitpoints);
					actionTimer = 7;
				}
				return true;
			}
		}
		return false;
	}
	public boolean ResetAttackNPC() {
		if (attacknpc > -1 && attacknpc < Server.npcUpdater.maxNPCs) {
			Server.npcUpdater.npcs[attacknpc].IsUnderAttack = false;
		}
		IsAttackingNPC = false;
		attacknpc = -1;
		resetAnimation();
		return true;
	}
	public void ManipulateDirection() {
		//playerMD = Library.mutil.direction(absX, absY, skillX, skillY);
		if (playerMD != -1) {
			//playerMD >>= 1;
			updateRequired = true;
			dirUpdateRequired = true;
		}
	}

	public void ReplaceObject(int objectX, int objectY, int NewObjectID, int Face, int ObjectType) {
		outStream.createFrame(85);
		outStream.writeByteC(objectY - (mapRegionY * 8));
		outStream.writeByteC(objectX - (mapRegionX * 8));

		outStream.createFrame(101);
		outStream.writeByteC((ObjectType<<2) + (Face&3));
		outStream.writeByte(0);

		if (NewObjectID != -1) {
			outStream.createFrame(151);
			outStream.writeByteS(0);
			outStream.writeWordBigEndian(NewObjectID);
			outStream.writeByteS((ObjectType<<2) + (Face&3));
			//FACE: 0= WEST | -1 = NORTH | -2 = EAST | -3 = SOUTH
			//ObjectType: 0-3 wall objects, 4-8 wall decoration, 9: diag. walls, 10-11 world objects, 12-21: roofs, 22: floor decoration
		}
	}

	public int GetNPCID(int coordX, int coordY) {
		for (int i = 0; i < Server.npcUpdater.maxNPCs; i++) {
			if (Server.npcUpdater.npcs[i] != null) {
				if (Server.npcUpdater.npcs[i].absX == coordX && Server.npcUpdater.npcs[i].absY == coordY) {
					return Server.npcUpdater.npcs[i].npcType;
				}
			}
		}
		return 1;
	}
	public String GetNpcName(int NpcID) {
		for (int i = 0; i < Server.npcUpdater.maxListedNPCs; i++) {
			if (Server.npcUpdater.NpcList[i] != null) {
				if (Server.npcUpdater.NpcList[i].npcId == NpcID) {
					return Server.npcUpdater.NpcList[i].npcName;
				}
			}
		}
		return "Npc: "+NpcID;
	}
	public String GetItemName(int ItemID) {
		for (int i = 0; i < Server.itemHandler.MaxListedItems; i++) {
			if (Server.itemHandler.ItemList[i] != null) {
				if (Server.itemHandler.ItemList[i].itemId == ItemID) {
					return Server.itemHandler.ItemList[i].itemName;
				}
			}
		}
		return "Item: "+ItemID;
	}
	public double GetItemShopValue(int ItemID, int Type, int fromSlot) {
		double ShopValue = 1;
		double Overstock = 0;
		double TotPrice = 0;
		for (int i = 0; i < Server.itemHandler.MaxListedItems; i++) {
			if (Server.itemHandler.ItemList[i] != null) {
				if (Server.itemHandler.ItemList[i].itemId == ItemID) {
					ShopValue = Server.itemHandler.ItemList[i].ShopValue;
				}
			}
		}
		Overstock = Server.shopHandler.ShopItemsN[MyShopID][fromSlot] - Server.shopHandler.ShopItemsSN[MyShopID][fromSlot];
		TotPrice = (ShopValue * 1.26875); //Calculates price for 1 item, in db is stored for 0 items (strange but true)
		if (Overstock > 0) { //more then default -> cheaper
			TotPrice -= ((ShopValue / 100) * (1.26875 * Overstock));
		} else if (Overstock < 0) { //less then default -> exspensive
			TotPrice += ((ShopValue / 100) * (1.26875 * Overstock));
		}
		if (Server.shopHandler.ShopBModifier[MyShopID] == 1) {
			TotPrice *= 1.25; //25% more expensive (general stores only)
			if (Type == 1) {
				TotPrice *= 0.4; //general store buys item at 40% of its own selling value
			}
		} else if (Type == 1) {
			TotPrice *= 0.6; //other stores buy item at 60% of their own selling value
		}
		return TotPrice;
	}
	public int GetUnnotedItem(int ItemID) {
		int NewID = 0;
		String NotedName = "";
		for (int i = 0; i < Server.itemHandler.MaxListedItems; i++) {
			if (Server.itemHandler.ItemList[i] != null) {
				if (Server.itemHandler.ItemList[i].itemId == ItemID) {
					NotedName = Server.itemHandler.ItemList[i].itemName;
				}
			}
		}
		for (int i = 0; i < Server.itemHandler.MaxListedItems; i++) {
			if (Server.itemHandler.ItemList[i] != null) {
				if (Server.itemHandler.ItemList[i].itemName == NotedName) {
					if (Server.itemHandler.ItemList[i].itemDescription.startsWith("Swap this note at any bank for a") == false) {
						NewID = Server.itemHandler.ItemList[i].itemId;
						break;
					}
				}
			}
		}
		return NewID;
	}
		
	  public int distanceToPoint(int pointX,int pointY) {
		return(int) Math.sqrt(Math.pow(absX - pointX, 2) + Math.pow(absY - pointY, 2));
      }
	
	
	public void WriteEnergy() {
		if (playerRights < 2 && playerEnergy > 100) {
			playerEnergy = 100;
		}
		sendFrame126(playerEnergy + "%", 149);
	}
	public void ResetBonus() {
		for (int i = 0; i < playerBonus.length; i++) {
			playerBonus[i] = 0;
		}
	}
	public void GetBonus() {
		for (int i = 0; i < playerEquipment.length; i++) {
			if (playerEquipment[i] > -1) {
				for (int j = 0; j < Server.itemHandler.MaxListedItems; j++) {
					if (Server.itemHandler.ItemList[i] != null && Server.itemHandler.ItemList[j] != null) {
							if (Server.itemHandler.ItemList[j].itemId == playerEquipment[i]) {
							for (int k = 0; k < playerBonus.length; k++) {
								playerBonus[k] += Server.itemHandler.ItemList[j].Bonuses[k];
							}
							break;
						}
					}
				}
			}
		}
	}
	public void WriteBonus() {
		int offset = 0;
		String send = "";
		for (int i = 0; i < playerBonus.length; i++) {
			if (playerBonus[i] >= 0) {
				send = BonusName[i]+": +"+playerBonus[i];
			} else {
				send = BonusName[i]+": -"+java.lang.Math.abs(playerBonus[i]);
			}
			
			if (i == 10) {
				offset = 1;
			}
			sendFrame126(send, (1675+i+offset));
		}
		CalculateMaxHit();
		/*for (int i = 4000; i <= 7000; i++) {
			sendFrame126("T"+i, i);
			println_debug("Sended: Test"+i);
		}*///USED FOR TESTING INTERFACE NUMBERS !
	}
	
	
	
	public void AddObjectFire() {
		if (IsFireing == false) {
			IsFireing = true;
			int tmpX = 0;
			int tmpY = 0;
			int calcX = 0;
			int calcY = 0;
			for (int i = 0; i < ObjectUpdater.MaxObjects; i++) {
				//if (server.itemHandler.DroppedItemsID[i] > -1) {
					tmpX = ObjectUpdater.ObjectFireX[i];
					tmpY = ObjectUpdater.ObjectFireY[i];
					calcX = tmpX - absX;
					calcY = tmpY - absY;
					if (calcX >= -16 && calcX <= 15 && calcY >= -16 && calcY <= 15 && FireDelete[i] == false && ObjectUpdater.ObjectFireH[i] == heightLevel) {
						if (IsFireShowed[i] == false) {
							IsFireShowed[i] = true;
							ReplaceObject(ObjectUpdater.ObjectFireX[i], ObjectUpdater.ObjectFireY[i], ObjectUpdater.ObjectFireID[i], 0, 10);
						}
					} else if (IsFireShowed[i] == true || FireDelete[i] == true) {
						ReplaceObject(ObjectUpdater.ObjectFireX[i], ObjectUpdater.ObjectFireY[i], -1, 0, 10);
						int LastPlayerInList = -1;
						int TotalPlayers = 0;
						for (int j = 1; j < ClientUpdater.maxPlayers; j++) {
							if (ClientUpdater.players[j] != null) {
								LastPlayerInList = j;
								TotalPlayers++;
							}
						}
						if (FireDelete[i] == true) {
							FireDelete[i] = false;
							ObjectUpdater.ObjectFireDeletecount[i]++;
							if ((LastPlayerInList == playerId || LastPlayerInList == -1) && ObjectUpdater.ObjectFireDeletecount[i] == TotalPlayers) {
								int ashX = ObjectUpdater.ObjectFireX[i];
								int ashY = ObjectUpdater.ObjectFireY[i];
								ObjectUpdater.ResetFire(i);
								for (int j = 1; j < ClientUpdater.maxPlayers; j++) {
									if (ClientUpdater.players[j] != null) {
										ClientUpdater.players[j].IsFireShowed[i] = false;
									}
								}
									ItemUpdater.addItem(592, ashX, ashY, 1, playerId, false);
							}
						} else {
							IsFireShowed[i] = false;
						}
					}
				//}
			}
			IsFireing = false;
		}
	}	
	
	
	
	public void CalculateMaxHit() {
		double MaxHit = 0;
		int StrBonus = playerBonus[10]; //Strength Bonus
		int Strength = playerLevel[playerStrength]; //Strength
		if (FightType == 1 || FightType == 4) { //Accurate & Defensive
			MaxHit += (double)(1.05 + (double)((double)(StrBonus * Strength) * 0.00175));
		} else if (FightType == 2) { //Aggresive
			MaxHit += (double)(1.35 + (double)((double)(StrBonus) * 0.00525));
		} else if (FightType == 3) { //Controlled
			MaxHit += (double)(1.15 + (double)((double)(StrBonus) * 0.00175));
		}
		MaxHit += (double)(Strength * 0.1);
		if (StrPotion == 1) { //Strength Potion
			MaxHit += (double)(Strength * 0.0014);
		} else if (StrPotion == 2) { //Super Strength Potion
			MaxHit += (double)(Strength * 0.0205);
		}
		if (StrPrayer == 1) { //Burst Of Strength
			MaxHit += (double)(Strength * 0.005);
		} else if (StrPrayer == 2) { //Super Human Strength
			MaxHit += (double)(Strength * 0.01);
		} else if (StrPrayer == 3) { //Ultimate Strength
			MaxHit += (double)(Strength * 0.015);
		}
		playerMaxHit = (int)Math.floor(MaxHit);
	}
	public boolean GoodDistance(int objectX, int objectY, int playerX, int playerY, int distance) {
		for (int i = 0; i <= distance; i++) {
		  for (int j = 0; j <= distance; j++) {
			if ((objectX + i) == playerX && ((objectY + j) == playerY || (objectY - j) == playerY || objectY == playerY)) {
				return true;
			} else if ((objectX - i) == playerX && ((objectY + j) == playerY || (objectY - j) == playerY || objectY == playerY)) {
				return true;
			} else if (objectX == playerX && ((objectY + j) == playerY || (objectY - j) == playerY || objectY == playerY)) {
				return true;
			}
		  }
		}
		return false;
	}
	public boolean GoodDistance2(int objectX, int objectY, int playerX, int playerY, int distance) {
		for (int i = 0; i <= distance; i++) {
		  for (int j = 0; j <= distance; j++) {
			if (objectX == playerX && ((objectY + j) == playerY || (objectY - j) == playerY || objectY == playerY)) {
				return true;
			} else if (objectY == playerY && ((objectX + j) == playerX || (objectX - j) == playerX || objectX == playerX)) {
				return true;
			}
		  }
		}
		return false;
	}
/*TRADING*/
	public void AcceptTrade() {
		sendFrame248(3323, 3321); //trading window + bag
		resetItems(3322);
		resetTItems(3415);
		resetOTItems(3416);
		sendFrame126("Trading With: "+ClientUpdater.players[tradeWith].playerName, 3417);
		sendFrame126("", 3431);
	}
	public void DeclineTrade() {
		for (int i = 0; i < playerTItems.length; i++) {
			if (playerTItems[i] > 0) {
				fromTrade((playerTItems[i] - 1), i, playerTItemsN[i]);
			}
		}
		resetItems(3214);
		resetTrade();
	}
	public void resetTrade() {
		tradeWith = 0;
		tradeWaitingTime = 0;
		tradeStatus = 0;
		tradeUpdateOther = false;
		tradeOtherDeclined = false;
		WanneTrade = 0;
		WanneTradeWith = 0;
		TradeConfirmed = false;
		for (int i = 0; i < playerTItems.length; i++) {
			playerTItems[i] = 0;
			playerTItemsN[i] = 0;
			playerOTItems[i] = 0;
			playerOTItemsN[i] = 0;
		}
	}
	public void ConfirmTrade() {
		if (TradeConfirmed == false) {
			RemoveAllWindows();
			for (int i = 0; i < playerOTItems.length; i++) {
				if (playerOTItems[i] > 0) {
					addItem((playerOTItems[i] - 1), playerOTItemsN[i]);
				}
			}
			resetItems(3214);
			TradeConfirmed = true;
		}
	}
	public void TradeGoConfirm() {
		sendFrame248(3443, 3213); //trade confirm + normal bag
		resetItems(3214);
		String SendTrade = "Absolutely nothing!";
		String SendAmount = "";
		int Count = 0;
		for (int i = 0; i < playerTItems.length; i++) {
			if (playerTItems[i] > 0) {
				if (playerTItemsN[i] >= 1000 && playerTItemsN[i] < 1000000) {
					SendAmount = "@cya@" + (playerTItemsN[i] / 1000) + "K @whi@(" + playerTItemsN[i] + ")";
				} else if (playerTItemsN[i] >= 1000000) {
					SendAmount = "@gre@" + (playerTItemsN[i] / 1000000) + " million @whi@(" + playerTItemsN[i] + ")";
				} else {
					SendAmount = "" + playerTItemsN[i];
				}
				if (Count == 0) {
					SendTrade = GetItemName((playerTItems[i] - 1));
				} else {
					SendTrade = SendTrade + "\\n" + GetItemName((playerTItems[i] - 1));
				}
				if (Item.itemIsNote[(playerTItems[i] - 1)] == true || Item.itemStackable[(playerTItems[i] - 1)] == true) {
					SendTrade = SendTrade + " x " + SendAmount;
				}
				Count++;
			}
		}
		sendFrame126(SendTrade, 3557);
		SendTrade = "Absolutely nothing!";
		SendAmount = "";
		Count = 0;
		for (int i = 0; i < playerOTItems.length; i++) {
			if (playerOTItems[i] > 0) {
				if (playerOTItemsN[i] >= 1000 && playerOTItemsN[i] < 1000000) {
					SendAmount = "@cya@" + (playerOTItemsN[i] / 1000) + "K @whi@(" + playerOTItemsN[i] + ")";
				} else if (playerOTItemsN[i] >= 1000000) {
					SendAmount = "@gre@" + (playerOTItemsN[i] / 1000000) + " million @whi@(" + playerOTItemsN[i] + ")";
				} else {
					SendAmount = "" + playerOTItemsN[i];
				}
				if (Count == 0) {
					SendTrade = GetItemName((playerOTItems[i] - 1));
				} else {
					SendTrade = SendTrade + "\\n" + GetItemName((playerOTItems[i] - 1));
				}
				if (Item.itemIsNote[(playerOTItems[i] - 1)] == true || Item.itemStackable[(playerOTItems[i] - 1)] == true) {
					SendTrade = SendTrade + " x " + SendAmount;
				}
				Count++;
			}
		}
		sendFrame126(SendTrade, 3558);
	}
	public boolean fromTrade(int itemID, int fromSlot, int amount) {
		if (amount > 0 && (itemID + 1) == playerTItems[fromSlot]) {
			if (amount > playerTItemsN[fromSlot]) {
				amount = playerTItemsN[fromSlot];
			}
			addItem((playerTItems[fromSlot] - 1), amount);
			if (amount == playerTItemsN[fromSlot]) {
				playerTItems[fromSlot] = 0;
				ClientUpdater.players[tradeWith].playerOTItems[fromSlot] = 0;
			}
			playerTItemsN[fromSlot] -= amount;
			ClientUpdater.players[tradeWith].playerOTItemsN[fromSlot] -= amount;
			resetItems(3322);
			resetTItems(3415);
			ClientUpdater.players[tradeWith].tradeUpdateOther = true;
			if (ClientUpdater.players[tradeWith].tradeStatus == 3) {
				ClientUpdater.players[tradeWith].tradeStatus = 2;
				ClientUpdater.players[tradeWith].AntiTradeScam = true;
				sendFrame126("", 3431);
			}
			return true;
		}
		return false;
	}
	public boolean tradeItem(int itemID, int fromSlot, int amount) {
		if (tradeWith > 0) {
			if (ClientUpdater.players[tradeWith] == null) {
				DeclineTrade();
				return false;
			}
		} else {
			DeclineTrade();
			return false;
		}
		if (amount > 0 && itemID == (playerItems[fromSlot] - 1)) {
			if (amount > playerItemsN[fromSlot]) {
				amount = playerItemsN[fromSlot];
			}
			boolean IsInTrade = false;
			for (int i = 0; i < playerTItems.length; i++) {
				if (playerTItems[i] == playerItems[fromSlot]) {
					if (Item.itemStackable[(playerItems[fromSlot] - 1)] == true || Item.itemIsNote[(playerItems[fromSlot] - 1)] == true) {
						playerTItemsN[i] += amount;
						ClientUpdater.players[tradeWith].playerOTItemsN[i] += amount;
						IsInTrade = true;
						break;
					}
				}
			}
			if (IsInTrade == false) {
				for (int i = 0; i < playerTItems.length; i++) {
					if (playerTItems[i] <= 0) {
						playerTItems[i] = playerItems[fromSlot];
						playerTItemsN[i] = amount;
						ClientUpdater.players[tradeWith].playerOTItems[i] = playerItems[fromSlot];
						ClientUpdater.players[tradeWith].playerOTItemsN[i] = amount;
						break;
					}
				}
			}
			if (amount == playerItemsN[fromSlot]) {
				playerItems[fromSlot] = 0;
			}
			playerItemsN[fromSlot] -= amount;
			resetItems(3322);
			resetTItems(3415);
			ClientUpdater.players[tradeWith].tradeUpdateOther = true;
			if (ClientUpdater.players[tradeWith].tradeStatus == 3) {
				ClientUpdater.players[tradeWith].tradeStatus = 2;
				ClientUpdater.players[tradeWith].AntiTradeScam = true;
				sendFrame126("", 3431);
			}
			return true;
		}
		return false;
	}
/*Shops*/
	public boolean sellItem(int itemID, int fromSlot, int amount) {
		if (amount > 0 && itemID == (playerItems[fromSlot] - 1)) {
			if (Server.shopHandler.ShopSModifier[MyShopID] > 1) {
				boolean IsIn = false;
				for (int i = 0; i <= Server.shopHandler.ShopItemsStandard[MyShopID]; i++) {
					if (itemID == (Server.shopHandler.ShopItems[MyShopID][i] - 1)) {
						IsIn = true;
						break;
					}
				}
				if (IsIn == false) {
					sendMessage("You cannot sell "+GetItemName(itemID)+" in this store.");
					return false;
				}
			}
			if (Item.itemSellable[(playerItems[fromSlot] - 1)] == false) {
				sendMessage("I cannot sell "+GetItemName(itemID)+".");
				return false;
			}
			if (amount > playerItemsN[fromSlot] && (Item.itemIsNote[(playerItems[fromSlot] - 1)] == true || Item.itemStackable[(playerItems[fromSlot] - 1)] == true)) {
				amount = playerItemsN[fromSlot];
			} else if (amount > GetXItemsInBag(itemID) && Item.itemIsNote[(playerItems[fromSlot] - 1)] == false && Item.itemStackable[(playerItems[fromSlot] - 1)] == false) {
				amount = GetXItemsInBag(itemID);
			}
			double ShopValue;
			double TotPrice;
			int TotPrice2;
			int Overstock;
			for (int i = amount; i > 0; i--) {
				TotPrice2 = (int)Math.floor(GetItemShopValue(itemID, 1, fromSlot));
				if (freeSlots() > 0) {
					if (Item.itemIsNote[itemID] == false) {
						deleteItem(itemID, GetItemSlot(itemID), 1);
					} else {
						deleteItem(itemID, fromSlot, 1);
					}
					addItem(995, TotPrice2);
					addShopItem(itemID, 1);
				} else {
					sendMessage("Not enough space in your inventory.");
					break;
				}
			}
			resetItems(3823);
			resetShop(MyShopID);
			UpdatePlayerShop();
			return true;
		}
		return true;
	}
	public boolean buyItem(int itemID, int fromSlot, int amount) {
		if (amount > 0 && itemID == (Server.shopHandler.ShopItems[MyShopID][fromSlot] - 1)) {
			if (amount > Server.shopHandler.ShopItemsN[MyShopID][fromSlot]) {
				amount = Server.shopHandler.ShopItemsN[MyShopID][fromSlot];
			}
			double ShopValue;
			double TotPrice;
			int TotPrice2;
			int Overstock;
			int Slot = 0;
			for (int i = amount; i > 0; i--) {
				TotPrice2 = (int)Math.floor(GetItemShopValue(itemID, 0, fromSlot));
				Slot = GetItemSlot(995);
				if (Slot == -1) {
					sendMessage("You don't have enough coins.");
					break;
				}
				if (playerItemsN[Slot] >= TotPrice2) {
					if (freeSlots() > 0) {
						deleteItem(995, GetItemSlot(995), TotPrice2);
						addItem(itemID, 1);
						Server.shopHandler.ShopItemsN[MyShopID][fromSlot] -= 1;
						Server.shopHandler.ShopItemsDelay[MyShopID][fromSlot] = 0;
						if ((fromSlot + 1) > Server.shopHandler.ShopItemsStandard[MyShopID]) {
							Server.shopHandler.ShopItems[MyShopID][fromSlot] = 0;
						}
					} else {
						sendMessage("Not enough space in your inventory.");
						break;
					}
				} else {
					sendMessage("You don't have enough coins.");
					break;
				}
			}
			resetItems(3823);
			resetShop(MyShopID);
			UpdatePlayerShop();
			return true;
		}
		return false;
	}
	public void UpdatePlayerShop() {
		for (int i = 1; i < ClientUpdater.maxPlayers; i++) {
			if (ClientUpdater.players[i] != null) {
				if (ClientUpdater.players[i].IsShopping == true && ClientUpdater.players[i].MyShopID == MyShopID && i != playerId) {
					ClientUpdater.players[i].UpdateShop = true;
				}
			}
		}
	}
	public boolean addShopItem(int itemID, int amount) {
		boolean Added = false;
		if (amount <= 0) {
			return false;
		}
		if (Item.itemIsNote[itemID] == true) {
			itemID = GetUnnotedItem(itemID);
		}
		for (int i = 0; i < Server.shopHandler.ShopItems.length; i++) {
			if ((Server.shopHandler.ShopItems[MyShopID][i] - 1) == itemID) {
				Server.shopHandler.ShopItemsN[MyShopID][i] += amount;
				Added = true;
			}
		}
		if (Added == false) {
			for (int i = 0; i < Server.shopHandler.ShopItems.length; i++) {
				if (Server.shopHandler.ShopItems[MyShopID][i] == 0) {
					Server.shopHandler.ShopItems[MyShopID][i] = (itemID + 1);
					Server.shopHandler.ShopItemsN[MyShopID][i] = amount;
					Server.shopHandler.ShopItemsDelay[MyShopID][i] = 0;
					break;
				}
			}
		}
		return true;
	}
/*NPC Talking*/
	public void UpdateNPCChat() {
		/*sendFrame126("", 4902);
		sendFrame126("", 4903);
		sendFrame126("", 4904);
		sendFrame126("", 4905);
		sendFrame126("", 4906);*/
		sendFrame126("", 976);
		if (Server.dialogueHandler.DialogueType[NpcDialogue] == 1) { //npc 1 chat line (click here to continue)
			sendFrame200(4883, 591);
			sendFrame126(GetNpcName(NpcTalkTo), 4884);
			sendFrame126(Server.dialogueHandler.DialogueText[NpcDialogue][1], 4885);
			sendFrame75(NpcTalkTo, 4883);
			sendFrame164(4882);
		} else if (Server.dialogueHandler.DialogueType[NpcDialogue] == 2) { //npc 2 option line
			sendFrame171(Server.dialogueHandler.DialogueSword[NpcDialogue][1], 2465); //swords close to eachother
			sendFrame171(Server.dialogueHandler.DialogueSword[NpcDialogue][1], 2468); //swords far away
			sendFrame126(Server.dialogueHandler.DialogueQuestion[NpcDialogue], 2460);
			sendFrame126(Server.dialogueHandler.DialogueText[NpcDialogue][1], 2461);
			sendFrame126(Server.dialogueHandler.DialogueText[NpcDialogue][2], 2462);
			sendFrame164(2459);
		} else if (Server.dialogueHandler.DialogueType[NpcDialogue] == 3) { //player 2 chat line (click here to continue)
			sendFrame200(615, 974);
			sendFrame126(playerName, 975);
			sendFrame126(Server.dialogueHandler.DialogueText[NpcDialogue][1], 976);
			sendFrame126(Server.dialogueHandler.DialogueText[NpcDialogue][2], 977);
			sendFrame185(974);
			sendFrame164(973);
		}
		NpcDialogueSend = true;
		/*sendFrame200(4901, 554);
		sendFrame126(GetNpcName(NpcTalkTo), 4902);
		sendFrame126("Good day, how can I help you?", 4904);
		sendFrame75(NpcTalkTo, 4901);
		sendFrame164(4900);
		*/
	}
	public void DialogueAction(int Action) {
		switch (Action) {
			case -1:
				openUpBank();
				break;
			case -2:
				openUpShop(2);
				break;
			case -3:
				openUpPinSettings();
				break;
		}
	}
/*Equipment level checking*/
	public int GetCLAttack(int ItemID) {
		if (ItemID == -1) {
			return 1;
		}
		String ItemName = GetItemName(ItemID);
		String ItemName2 = ItemName.replaceAll("Bronze", "");
		ItemName2 = ItemName2.replaceAll("Iron", "");
		ItemName2 = ItemName2.replaceAll("Steel", "");
		ItemName2 = ItemName2.replaceAll("Black", "");
		ItemName2 = ItemName2.replaceAll("Mithril", "");
		ItemName2 = ItemName2.replaceAll("Adamant", "");
		ItemName2 = ItemName2.replaceAll("Rune", "");
		ItemName2 = ItemName2.replaceAll("Granite", "");
		ItemName2 = ItemName2.replaceAll("Dragon", "");
		ItemName2 = ItemName2.replaceAll("Crystal", "");
		ItemName2 = ItemName2.trim();
		if (ItemName2.startsWith("claws")
		 || ItemName2.startsWith("dagger")
		 || ItemName2.startsWith("sword")
		 || ItemName2.startsWith("scimitar")
		 || ItemName2.startsWith("mace")
		 || ItemName2.startsWith("longsword")
		 || ItemName2.startsWith("battleaxe")
		 || ItemName2.startsWith("warhammer")
		 || ItemName2.startsWith("2h sword")
		 || ItemName2.startsWith("harlberd")) {
			if (ItemName.startsWith("Bronze")) {
				return 1;
			} else if (ItemName.startsWith("Iron")) {
				return 1;
			} else if (ItemName.startsWith("Steel")) {
				return 5;
			} else if (ItemName.startsWith("Black")) {
				return 10;
			} else if (ItemName.startsWith("Mithril")) {
				return 20;
			} else if (ItemName.startsWith("Adamant")) {
				return 30;
			} else if (ItemName.startsWith("Rune")) {
				return 40;
			} else if (ItemName.startsWith("Dragon")) {
				return 60;
			}
		} else if (ItemName.startsWith("Granite")) {
			return 50;
		} else if (ItemName.endsWith("whip") || ItemName.endsWith("Ahrims staff") || ItemName.endsWith("Torags hammers") || ItemName.endsWith("Veracs flail") || ItemName.endsWith("Guthans warspear") || ItemName.endsWith("Dharoks greataxe")) {
			return 70;
		}
		return 1;
	}
	public int GetCLDefence(int ItemID) {
		if (ItemID == -1) {
			return 1;
		}
		String ItemName = GetItemName(ItemID);
		String ItemName2 = ItemName.replaceAll("Bronze", "");
		ItemName2 = ItemName2.replaceAll("Iron", "");
		ItemName2 = ItemName2.replaceAll("Steel", "");
		ItemName2 = ItemName2.replaceAll("Black", "");
		ItemName2 = ItemName2.replaceAll("Mithril", "");
		ItemName2 = ItemName2.replaceAll("Adamant", "");
		ItemName2 = ItemName2.replaceAll("Rune", "");
		ItemName2 = ItemName2.replaceAll("Granite", "");
		ItemName2 = ItemName2.replaceAll("Dragon", "");
		ItemName2 = ItemName2.replaceAll("Crystal", "");
		ItemName2 = ItemName2.trim();
		if (ItemName2.startsWith("claws")
		 || ItemName2.startsWith("dagger")
		 || ItemName2.startsWith("sword")
		 || ItemName2.startsWith("scimitar")
		 || ItemName2.startsWith("mace")
		 || ItemName2.startsWith("longsword")
		 || ItemName2.startsWith("battleaxe")
		 || ItemName2.startsWith("warhammer")
		 || ItemName2.startsWith("2h sword")
		 || ItemName2.startsWith("harlberd")) {
			//It's a weapon, weapons don't required defence !
		} else if (ItemName.startsWith("Ahrims") ||  ItemName.startsWith("Karil") || ItemName.startsWith("Torag") || ItemName.startsWith("Verac") || ItemName.endsWith("Guthan") || ItemName.endsWith("Dharok")) {
			if (ItemName.endsWith("staff") || ItemName.endsWith("crossbow") || ItemName.endsWith("hammers") || ItemName.endsWith("flail") || ItemName.endsWith("warspear") || ItemName.endsWith("greataxe")) {
				//No defence for the barrow weapons
			} else {
				return 70;
			}
		} else {
			if (ItemName.startsWith("Bronze")) {
				return 1;
			} else if (ItemName.startsWith("Iron")) {
				return 1;
			} else if (ItemName.startsWith("Steel")) {
				return 5;
			} else if (ItemName.startsWith("Black")) {
				return 10;
			} else if (ItemName.startsWith("Mithril")) {
				return 20;
			} else if (ItemName.startsWith("Adamant")) {
				return 30;
			} else if (ItemName.startsWith("Rune")) {
				return 40;
			} else if (ItemName.startsWith("Dragon")) {
				return 60;
			}
		}
		return 1;
	}
	public int GetCLStrength(int ItemID) {
		if (ItemID == -1) {
			return 1;
		}
		String ItemName = GetItemName(ItemID);
		if (ItemName.startsWith("Granite")) {
			return 50;
		} else if (ItemName.startsWith("Torags hammers") || ItemName.endsWith("Dharoks greataxe")) {
			return 70;
		}
		return 1;
	}
	public int GetCLMagic(int ItemID) {
		if (ItemID == -1) {
			return 1;
		}
		String ItemName = GetItemName(ItemID);
		if (ItemName.startsWith("Ahrim")) {
			return 70;
		}
		return 1;
	}
	public int GetCLRanged(int ItemID) {
		if (ItemID == -1) {
			return 1;
		}
		String ItemName = GetItemName(ItemID);
		if (ItemName.startsWith("Karil")) {
			return 70;
		}
		return 1;
	}
/*WORLD*/
	public int GetWorld(int PlayerID) {
	return 1;
	}
/*OBJECTS*/
	public int GetObject(int X, int Y, int ObjectID) {
		for(int i = 0; i < Server.objectUpdater.MaxObjects; i++) {
			if (Server.objectUpdater.ObjectID[i] > -1) {
				if (X == Server.objectUpdater.ObjectX[i] && Y == Server.objectUpdater.ObjectY[i]) {
					if (ObjectID != -1) {
						if (ObjectID == Server.objectUpdater.ObjectID[i]) {
							return i;
						}
					} else {
						return i;
					}
				}
			}
		}
		return -1;
	}
	
	public int pickupID = 0;
	public int pickupAmt = 0;
	public int pickupX = 0;
	public int pickupY = 0;
	public boolean pickingUp = false;
	public void resetPickup() {
		pickupID = 0;
		pickupAmt = 0;
		pickupX = 0;
		pickupY = 0;
		pickingUp = false;
	}
	
	public void ChangeDoor(int ArrayID) {
		int objectID = Server.objectUpdater.ObjectOriID[ArrayID];
		int objectX = Server.objectUpdater.ObjectX[ArrayID];
		int objectY = Server.objectUpdater.ObjectY[ArrayID];
		int Face = Server.objectUpdater.ObjectFace[ArrayID];
		int Type = Server.objectUpdater.ObjectType[ArrayID];
		ReplaceObject(objectX, objectY, -1, -1, 0);
		switch (Type) {
			case 1:
				ReplaceObject(objectX, (objectY + 1), objectID, Face, 0);
				Server.objectUpdater.ObjectType[ArrayID] = 2;
				break;
			case 2:
				ReplaceObject(objectX, (objectY - 1), objectID, Face, 0);
				Server.objectUpdater.ObjectType[ArrayID] = 1;
				break;
			case 3:
				ReplaceObject((objectX + 1), objectY, objectID, Face, 0);
				Server.objectUpdater.ObjectType[ArrayID] = 4;
				break;
			case 4:
				ReplaceObject((objectX - 1), objectY, objectID, Face, 0);
				Server.objectUpdater.ObjectType[ArrayID] = 3;
				break;
		}
	}
}
